x

A Daily-Symfony-Quick-Setup-Zen-Cheatsheet

July 2nd, 2009
post #137 

Making the transition to Symfony 1.2 and Doctrine all at once was never going to be easy. As Doctrine is the future of symfony and I have a distinct Propel addiction, the following steps (based on the early stages of the excellent Jobeet tutorial) will take no time at all and can be practised often to help cement the process in mind until it’s second nature.

This is no substitute for (and will make little sense without first reading) the Jobeet tutorial, nor the documentation. This is just my daily-Symfony-quick-setup-zen-cheatsheet. I hope in time to be doing this one-handed in my sleep while vaccuuming the stairs. Copy+Paste strictly out of bounds.

If you choose to use this and repeat it often, you’ll have setup your web server config’ on your development setup ready to run this, so those steps are omitted.

Posted here in a bit of a rush to respond to Jwage’s request , I hope they live up to expectation, and that someone finds them useful. I am bound to have made some errors, some omissions or not been concise enough, please let me know.

Create The Project

  • mkdir <path_to_local dev>\newsymfonytest
  • cd <path_to_local dev>\newsymfonytest

From now on<path_to_local dev>\newsymfonytest is your <project> directory

  • php <path_to_symfony>\data\bin\symfony generate:project newsymfonytest
    • Note that this creates an absolute path to Symfony in <project>/config/ProjectConfiguration.class.php which you should update.
  • copy the sf folder from  <path_to_symfony>\data\web\ into <project>/apps/frontend/web or alias it in your server configuration Alias /sf “<path_to_symfony>\data\web\sf”
  • Now Symfony is linked from your current location, the <project> root, test local access to Command-Line Interface with php symfony cc
  • Check the application has been created by visiting in browser

Setup Doctrine Database

  • Replace the setup function in <project>/config/ProjectConfiguration.class.php
public function setup()
{
  $this->enablePlugins(array('sfDoctrinePlugin'));
  $this->disablePlugins(array('sfPropelPlugin'));
}
  • Publish any plugin assets: php symfony plugin:publish-assets
  • Clear the Cache php symfony cc
  • Remove Propel structure, create Doctrine structure:
    • rm config/propel.ini
    • rm config/schema.yml
    • rm config/databases.yml
    • mkdir config/doctrine
  • create database in MySQL: mysqladmin -u root -p create newsymfonytest
  • << enter password when prompted or omit -p if you have no password set (shame on you!) >>
  • setup the YAML schema in <project>/config/doctrine/schema.yml

Here’s my sample schema.yml, lifted from the Jobeet tutorial:

# config/doctrine/schema.yml
SampleCategory:
  actAs: { Timestampable: ~ }
  columns:
    name: { type: string(255), notnull: true, unique: true }

SampleItem:
  actAs: { Timestampable: ~ }
  columns:
    category_id:  { type: integer, notnull: true }
    type:         { type: string(255) }
    is_activated: { type: boolean, notnull: true, default: 0 }
    email:        { type: string(255), notnull: true }
    expires_at:   { type: timestamp, notnull: true }
  relations:
    SampleCategory: { onDelete: CASCADE, local: category_id, foreign: id, foreignAlias: SampleItems }
  •  Generate a new Databases.yml:

php symfony configure:database –name=doctrine –class=sfDoctrineDatabase “mysql:host=localhost;dbname=newsymfonytest” <mysqluser> <mysqlpass>

Build!!!

  • php symfony doctrine:build-model
  • php symfony doctrine:build-sql
  • php symfony doctrine:insert-sql
  • php symfony doctrine:build-forms

Add Sample Data

Create fixture files:

Here’s my sample <project>data/fixtures/categories.yml, again lifted from the Jobeet tutorial:

SampleCategory:
  design:
    name: Design
  programming:
    name: Programming
  manager:
    name: Manager
  administrator:
    name: Administrator

Here’s my sample <project>data/fixtures/items.yml, curiously similar to one from the Jobeet tutorial I’ve said so little about.

SampleItem:
  job_sensio_labs:
    SampleCategory: programming
    type:         full-time
    is_activated: true
    email:        job@example.com
    expires_at:   '2010-10-10'
  • Populate with php symfony doctrine:data-load

Generate first app

  • php symfony generate:app –escaping-strategy=on –csrf-secret=1sTh15r34l1y53cur3 frontend
  • Visit the site root you set up in your server configuration in your browser

Generate first module

  • Then, using the format:
  "php symfony doctrine:generate-module --with-show --non-verbose-templates <appname> <modulename> <modelname>"

php symfony doctrine:generate-module –with-show –non-verbose-templates frontend sample SampleItem

  • Visit the module in your browser
  • Rinse and repeat

Mixing Object and Form Helpers in Symfony

August 21st, 2008
post #125 

Being new to Symfony I’m still getting my head around some of its paradigms. Two months with the manual before embarking on any development taught me that it was worth pursuing, but there’re always areas you need to see working.

The Object form helpers looked particularly useful, so for my first production development I aim to use them wherever possible. These helpers allow you edit objects directly, simplifying the update process back in your actions.

sample form in editformSuccess.php template:

<?php echo form_tag('editform/updatetitle'); ?>
<?php echo object_input_hidden_tag($newsletter, 'getID') ;?>
Title: <?php echo object_input_tag($newsletter, 'getTitle') ;?>
<?php echo submit_tag('update'); ?>

and in actions.class.php:

<?php
public function executeEditform($request)
{
$this->newsletter = »
NewsletterPeer::retrieveByPk($request->getParameter('id'));
$this->forward404Unless($this->newsletter);
}

public function executeUpdatetitle($request)
{
$nltoupdate = NewsletterPeer::retrieveByPk($request->getParameter('id'));
$this->forward404Unless($nltoupdate );
$nltoupdate->fromArray(»
$this->getRequest()->getParameterHolder()->getAll(),BasePeer::TYPE_FIELDNAME);
$nltoupdate->save();
return $this->redirect(»
'newsletters/view?id='.$request->getParameter('id'));
}

The update code uses the fromArray method to update any properties of your object it holds data for, received from your form. Adding fields to your form doesn’t require changes to the action.

I got into difficulties when it came to setting a boolean field for my object, called “IsPublished”. Wishing to stick with the Object form helpers I investigated the Object_select_tag, however this has a different use altogether – allowing you to grab properties of other objects to match with your current object. The classic example being choosing an author from the authors object to match up to a post object.

I still wanted to save a property for my object, but I didn’t want to have it select from the object, or grab values from other objects. Further searches revealed I wasn’t alone in wondering how to set default selected values and generally get to grips with object_select_tag.

Mixing Object and Form helpers seemed the best solution, using select_tag for my boolean field. However this meant I wasn’t using the Object helper exclusively, so would it still work with fromArray?

The form code generated looked promisingly simple, so I tried a mix of object_input_tag and select_tag in my editformSuccess.php template:

<?php
$defaultOption = »
$newsletter->getIsPublished() == 1?1:0; # get current, set default
echo select_tag('in_published', options_for_select(array(»
0, 1),
$defaultOption));
?>

Note the highlighted property in select_tag. My Object Property is called “IsPublished”. To object-generate a plain text input field I’d have used:

<?php
Published: <?php echo object_input_tag($newsletter, 'getIsPublished') ;
?>

So my current field value would be retrieved, and the Object helper generates form fields using BasePeer::TYPE_FIELDNAME which in turn is used in my fromArray method to update the Db.

Normally one would use select_tag with internal field names (BasePeer:: TYPE:PHP_NAME) and write more action code to marry them up before a save(), however here I have to add my database field name into my view code.

Tethering your templates to your database schema is a route no-one should go down. So the internal name should be converted to the Db name on-the-fly in your template. The Peer classes have a function for this, and its public. The following call converts your usual internal field name for you, ready to drop into your select_tag:


<?php
$IsPublished_translated = BaseNewsletterPeer::translateFieldName(»'IsPublished',BasePeer::TYPE_PHPNAME, BasePeer::TYPE_FIELDNAME )
?>

You could assign this in your action, but it works just as well in the template:

<?php
echo select_tag(»
'BaseNewsletterPeer::translateFieldName(»
'IsPublished',BasePeer::TYPE_PHPNAME, BasePeer::TYPE_FIELDNAME
',»
options_for_select(array(»
0, 1),
$defaultOption));
?>

A final step would be to migrate this into a function higher up that so as to make templates a little prettier when editing.