symfonynerds.com

Nerds who love the symfony-project

Not written by anyone at Symfony Nerds HQ, but  despite this obviously flaw, it’s a good read! :D Get it here. It’s basically a “7 days” step through of the new form system, helped me as a primer for the first dabble with forms in 1.1 I made.

I’ll also take this opportunity to appologise for the lack of 1.1 related articles appearing to date… This is driven purely by the fact the Symfony Nerds Data Centre (we’re yet to move to “the cloud” :p ) is still running 1.0 in the production environment, but we’re almost ready to begin migration to 1.1 and as of last week all our new apps will be coded in it, so more articles should be arriving soon. (Just don’t ask about the work I did on validating AJAX components of forms in 1.0 which is now useless!!!)

  • 0 Comments
  • Filed under: 1.1, forms
  • Lately I’ve been working on some Symfony batch components to load/export data into and out of a database. If you are looking for a way to send emails from your Symfony batch scripts there are two ways.

    1) Use An Action
    It is possible to use a pre-defined action within a module for sending emails. You can, for example do this:

    sfContext::getInstance()->getController()->sendEmail('module', 'mySendEmailAction');

    Where you have a module called ‘module’ and an action within that called ‘mySendEmailAction’. You do however, run into issues when you want to pass paramaters across from your batch script to your action. I havent figured that one out yet - so if you know,  let us know!

    The important thing to note with this option is that you will need to enable the is_internal setting in module.yml of your module.  The is_internal paramater allows you to restrict access to your action so that it only takes internal calls. To change this so that outside components (eg batch) can call your action, set is_internal to false. If you dont do this, you might get an error like this:

    Uncaught exception ’sfConfigurationException’ with message ‘Action”mySendEmailAction” from module “module” cannot be called directly’ in /usr/share/php/symfony/controller/sfController.class.php:237

    2) Directly use sfMail
    The other, simpler option is to use sfMail directly. Within your Symfony batch script, just write your own custom method to send mail.

    function sendEmail(){
      // class initialization
      $mail = new sfMail();
      $mail->initialize();
      $mail->setMailer('sendmail');
      $mail->setCharset('utf-8');
     
      // definition of the required parameters
      $mail->setSender('webmaster@my-company.com', 'Me');
      $mail->setFrom('info@my-company.com', 'My Company');
      $mail->addReplyTo('webmaster_copy@my-company.com');
      $mail->addAddress('test@test.com');
      $mail->setSubject('Those Symfony nerds are hot');
      $mail->setBody('Well.. they think they are');
      $mail->send();
    }

    Do you know of any other or better ways? Let us know! I’m not too sure how Symfony 1.1 tasks handels this, that will be another blog post in a few months time…

    Looking for Symfony Plugins…

    I was working on a project that I decided could do with some client side AJAX validation…. So a bit of digging around led me to sfYzAjaxValidationPlugin… I quickly found out that the old plugin faq’s now redirect to the new plugin site… The only problem was, the plugin I was after, and it seems a lot of other plugins, haven’t been migrated over yet.

    My forum post about it went unanswered, but last night I came across a post from Fabien in the symfony google group noting that for a limited time only, the old plugins site is available here : http://raw.trac.symfony-project.org/wiki/SymfonyPlugins

    Hopefully that will help others out looking for plugins that for whatever reason aren’t on the new site yet.

  • 1 Comment
  • Filed under: plugins
  • I’m working on a project that requires some batch data loads and export to excel functions. This was really the first time I’ve used Symfony batch.

    Here are some random tips that helped me write my batch script. I think the Symfony book could use a bit more documentation detail when it comes to symfony batch as there are some things that aren’t even mentioned. Note: This is for Symfony 1.0.

    Random Tip #1: Creating a symfony batch
    I’m amazed how the documentation was lacking the details of what to put in the symfony batch, they just need a better explanation. So here is an example:

    ./symfony init-batch default symfony-nerds-look-good backend

    In the example above, I’ve created a batch script called symfony-nerds-look-good, now, you might think that’s a problem in itself, but that’s another blog post! So the format of creating a batch job is of this is:

    ./symfony init-batch default scriptName appName

    Note that ‘default’ is the name of the batch template. You can define multiple batch templates, but most of the time, the ‘default’ should be all that you need.

    Random Tip #2: Symfony batch logs
    If you are used to logging some custom logs with the Symfony logging classes in your view, its different for a batch component. In the actions class, this is all you have to do to write a log:

    $this->logMessage("Creating spreadsheet...", "debug");

    However, in batch you must do the following:

    $logger = sfLogger::getInstance(); //firstly declare the instance of the sfLogger (otherwise you wont be able to log)
    $logger->log("Creating spreadsheet", SF_LOG_DEBUG); //Then use the standard symfony log constance (eg SF_LOG_DEBUG or SF_LOG_WARN) etc...

    So it is slightly different to how you might normally do it.

    Random Tip #3: Using model objects and the database with batch
    If you would like to use the generated ORM objects that Propel has generated for you, you wont be able to straight away. You will notice if you try to, you will get the error “No connection params set for propel”. You must first instantiate a sfDatabaseManager, then initialise it:

    $databaseManager = new sfDatabaseManager();
    $databaseManager->initialize();
    //Then you can access your model objects and write your criteria as per the usual way

    Hope this helps you get started. Do you have any tips with Symfony batch? Let us know!

    I am working on an interesting project where I have been given the task of creating a web interface that allows an authenticated and authorised user to conduct specific types of search on a huge data set.

    The data set begins as flat text logs which are transformed and loaded into a normalised schema - which was designed well before I got involved.  So, I have been very impressed by the way that propel and creole have consistently reverse engineered the schema and built a reliable model.

    This is not a post about Propel or Creole but I thought to put this into context since I have been given a development specification that requires me to present data on a browser in a manner different to the way in which it is ordered and layed out in the database schema.

    So - consider a table that has the following structure:

    id (auto increment unique id)
    my_date (of type date)
    my_date_as_int (a conversion of date to int eg 2008-08-06 would be 20080806)

    The insertion of dates into the above fields is not ordered - so id 1 may have an older date than id 2 and so on…for example:

    id my_date_as_int my_date
    1 20080602 2008-06-02
    2 20080724 2008-07-24
    3 20080723 2008-07-23
    4 20080411 2008-04-11
    5 20080412 2008-04-12

    My task was to create a “drop down” select tag that showed the above sorted in an ascending order by the date field.

    Step 1.  Create a __toString method to return the date field as opposed to the Id.

    public function __toString()
    {
    return $this->getMyDate();
    }


    Step 2.  Create a custom method in the relevant Peer class to get a sorted list:

    public static function getSortedDate()
    {
    $c = new Criteria();
    $c->addAscendingOrderByColumn(DatePeer::MY_DATE_AS_INT);
    $rs = DatePeer::doSelect($c);
    return $rs;
    }

    As you can see, I choose to sort by the integer representation of the date field, but you can use the MY_DATE field in the same manner.

    Step 3.  Create a drop down select_tag in your view.

    There are two options here.

    Option 1.  Standard form name, value pairs being the date and id fields respectivey.

    <?php echo object_select_tag('', 'getMyDate', array (
      'related_class' => 'Date',
      'peer_method' => 'getSortedDate',
      'include_blank' => true,
    )) ?>


    Option 2.  Form name, value pairs being the my_date and the my_date_as_int fields respectivey.

    <?php
      echo select_tag('', 
       objects_for_select(DatePeer::getSortedDate(), 'getMyDateAsInt','getMyDate'),
       array('id'=>"this_date",'name'=>"this_date"))
    ?>

    That is it! The view then renders a drop down select that is constructed firstly by a call to the getSortedDate method, which in turn returns an array of sorted items - each of which is shown in the drop down using the __toString method to convert from an id to the date.

    Today the guys at the Symfony Project announced plugins have a new home. Symfony Plugins.


    Symfony Plugins

    It’s great. Some great new features:

  • Each plugin has a dedicated page
  • Plugin developers have their own admin console to manage the plugin details - this will be great for the community
  • Each plugin clearly identifies which version its compatible with
  • This will help the developer community to get together and start contributing as one. It’s similar to Ubuntu Launchpad - not quite as advanced, but with the new introduction of developers being able to own plugins and contribute in such a clear way - its going to be a great addition to the community.

    Symfony ‘time’ input field

    Unless I’m just going blind, there is no mention of this in the manual, but if you want to have a dropdown on your form for someone to input a time, there is a helper for it… just use:

    echo select_time_tag('cutover_time', 'now');

    The first arg is the name for the field, the second is the time to display. ‘Now’ means it will display the current (to your server) time when someone loads the form.

    If you’re also using a input_date_tag in the same form (quite likely you’d get a date and time together), then the helper will be automatically loaded for you, but if you just had this on a form without an input_date_tag you would also need to include somewhere:

    use_helper('DateForm');
  • 2 Comments
  • Filed under: 1.0, forms
  • This was meant to be a helpful post on getting an ajax observe_field working on a radiobutton_tag, but it is just as likely to lead to frustration, because there is a problem with prototype which means it won’t work as you may expect (more on that later), but it may still be useful for some, so here’s how you do it:

    I have used two radio buttons, one each for for ‘Yes’ and ‘No’. I originally thought you needed to specify the id as an option, but you don’t, it’s made up of the name and value of the radio button, so for the first one below the id is radio_but_yes

    echo radiobutton_tag('radio_but[]', 'Yes', false);
    echo ' Yes   ';
    echo radiobutton_tag('radio_but[]', 'No', true);
    echo ' No';

    Then you just have the usual overserve field, here duplicated for each dropdown. You’ll note I also set script to true as the content I show when selecting yes will also have Javascript in it.

    echo observe_field('radio_but_yes', array(
            'update' => 'lower_div',
            'url'       => 'order/Content',
            'with'     => "'type=' + value",
    	'script'   => 'true'
    ));
     
    echo observe_field('radio_but_no', array(
            'update'   => 'lower_div',
            'url'      => 'order/Content',
            'with'     => "'type=' + value",
    	'script'   => 'true'
    ));

    And of course your Div to display the content.

    echo '<div id="lower_div"></div>';

    As I said though, it seems there is a problem with prototype (the ajax library Symfony is using to do this) in that it only fires once… So in my case ‘No’ is the default, if someone selects ‘Yes’ the new fields I want will be displayed, however if they then change their mind and switch back to ‘No’ the fields will still be displayed…

    So for now, you’ll probabaly only want to use this if that doesn’t matter… for me it does, because mandatory fields will be shown, and if the user doesn’t want them, it will be frustrating that the form won’t submit until they’re completed, so in this case I’m going to just use a checkbox, or you could use a dropdown, both of these work fine.

  • 5 Comments
  • Filed under: 1.0, ajax, forms
  • Symfony Tip: 1.1 Model Building

    Consider this a twitter post more than blog material… but I am just playing around with Symfony 1.1 CRUD generation, and it seems there is an extra step from v1.0… After generating your model, but before trying to generate a CRUD, you need to run the command:

    symfony propel:build-forms

    If you don’t, then when you do a symfony propel-generate-crud, you will get the error:

    Fatal error: Class 'CustomerForm' not found in /usr/share/php/symfony/generator/sfAdminGenerator.class.php on line 722

    In the example above its Class ‘CustomerForm’ because Customer was the name of the class I chose to try and generate the form for.

    I’m off to do some more reading on forms/CRUD in 1.1, I’m getting the feeling it’s going to be a LOT different to 1.0….eHabib, you better add another offline package for what I just linked to I think, it will be my weeks reading in the can… I mean office… (ok I did mean can)

  • 4 Comments
  • Filed under: 1.1, forms, generators
  • If you are writing your schema.yml file, the Symfony book isn’t too detailed as to what you can and can’t put in your schema.yml. I’d recommend you head over to the Propel Guide, and read the appendix for detailed documentation.