SlideShare a Scribd company logo
1 of 103
Download to read offline
Symfony 1.3 + Doctrine 1.2




                Symfony 1.3
                     +
                Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   1
Symfony 1.3 + Doctrine 1.2




               Continued Evolution
                 of Symfony 1.x



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   2
Symfony 1.3 + Doctrine 1.2




       Lots of new features,
    enhancements and bug fixes.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   3
Symfony 1.3 + Doctrine 1.2




     Out with the old and in with
              the new!



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   4
Symfony 1.3 + Doctrine 1.2




      Doctrine is the default ORM




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   5
Symfony 1.3 + Doctrine 1.2




              Propel is deprecated




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   6
Symfony 1.3 + Doctrine 1.2




 Propel is deprecated in 1.3 but
 not removed. It will be dropped
   completely in symfony 2.0



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   7
Symfony 1.3 + Doctrine 1.2




      Still want to use Propel? :)
       Generate your project with the new --orm option



         $ php /path/to/symfony generate:project foo --orm=Propel




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                        8
Symfony 1.3 + Doctrine 1.2




          New Symfony Features




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   9
Symfony 1.3 + Doctrine 1.2




      Use the --installer option to
       execute Symfony installer
                 scripts


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   10
Symfony 1.3 + Doctrine 1.2




      $ php /path/to/symfony generate:project --installer=my_installer.php




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                 11
Symfony 1.3 + Doctrine 1.2
 Now in your my_installer.php you can do things like...
   if (!$this->askConfirmation('Are you sure you want to run this installer?'))
   {
     return;
   }

   $this->installDir(dirname(__FILE__).'/skeleton');

   $this->runTask('plugin:publish-assets');

   $validator = new sfValidatorEmail(array(), array('invalid' => 'hmmm, it does not look like
   an email!'));
   $email = $this->askAndValidate('Please, give me your email:', $validator);

   $this->runTask('configure:author', sprintf("'%s'", $email));

   $secret = $this->ask('Give a unique string for the CSRF secret:');

   $this->runTask('generate:app', 'frontend --escaping-strategy=true --csrf-secret='.
   $secret);

   $this->runTask('plugin:install', 'sfDoctrineGuardPlugin');
   $this->reloadTasks();

   $this->runTask('guard:create-user', 'jwage changeme');
   $this->runTask('cache:clear');

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                                12
Symfony 1.3 + Doctrine 1.2




     It replaces the need to
   maintain your own skeleton
   symfony project. Just write
   your own custom installer to
 generate a new project the way
           you want it.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   13
Symfony 1.3 + Doctrine 1.2




                 Form Framework




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   14
Symfony 1.3 + Doctrine 1.2


 Recognize this?
               class LoginForm extends BaseUserForm
               {
                 public function configure()
                 {
                   unset(
                      $this['first_name'],
                      $this['last_name'],
                      $this['email_address']
                   );
                 }
               }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2          15
Symfony 1.3 + Doctrine 1.2




   Using unset() to remove fields




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   16
Symfony 1.3 + Doctrine 1.2




     Instead, lets say what form
   fields we WANT to use instead
      of the ones we don’t want



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   17
Symfony 1.3 + Doctrine 1.2


 Now it is possible with the useFields() method.

       class LoginForm extends BaseUserForm
       {
         public function configure()
         {
           $this->useFields(array(
             'username', 'password'
           ));
         }
       }


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2       18
Symfony 1.3 + Doctrine 1.2




                 Easier to maintain




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   19
Symfony 1.3 + Doctrine 1.2




      Does not require keeping
    unset() list updated when we
      add new fields to model


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   20
Symfony 1.3 + Doctrine 1.2




                    Forms + Events




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   21
Symfony 1.3 + Doctrine 1.2




  We now have a sfFormSymfony
  in core and BaseForm class in
          each project.


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   22
Symfony 1.3 + Doctrine 1.2




      Sits on top of the agnostic
     sfForm and couples symfony
       dispatcher with the form
              framework.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   23
Symfony 1.3 + Doctrine 1.2




   Allows us to dispatch symfony
    events from within the form
         framework. YES!



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   24
Symfony 1.3 + Doctrine 1.2




            What events can I use?




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   25
Symfony 1.3 + Doctrine 1.2



• form.post_configure - Notified after every form is
  configured

• form.filter_values - Filters tainted parameters and files
  array just prior to binding

• form.validation_error - Notified whenever form validation
  fails.

• form.method_not_found - Notified whenever an unknown
  method is called


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                  26
Symfony 1.3 + Doctrine 1.2




             Example Form Event

    Add easy ReCaptcha functionality to
                all forms



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   27
Symfony 1.3 + Doctrine 1.2


 Define a regular form that extends sfFormSymfony


  class MyForm extends BaseForm
  {
    public function configure()
    {
      $this->widgetSchema['title'] = new sfWidgetFormInputText();
      $this->validatorSchema['title'] = new sfValidatorString();

          $this->widgetSchema->setNameFormat('my_form[%s]');
      }
  }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                    28
Symfony 1.3 + Doctrine 1.2


 Connect events form.post_configure and form.filter_values
        class ProjectConfiguration extends sfProjectConfiguration
        {
          public function setup()
          {
            // ...

                $this->dispatcher->connect('form.post_configure', array(
                  $this, 'formPostConfigure'
                ));

                $this->dispatcher->connect('form.filter_values', array(
                  $this, 'formFilterValues'
                ));
            }
        }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                               29
Symfony 1.3 + Doctrine 1.2


 Define formPostConfigure() method.
         public function formPostConfigure(sfEvent $event)
         {
           $form = $event->getSubject();

             if ($form->reCaptcha)
             {
               $widgetSchema = $form->getWidgetSchema();
               $validatorSchema = $form->getValidatorSchema();
               $widgetSchema['captcha'] = new sfWidgetFormReCaptcha(array(
                 'public_key' => '6Ld2DgQAAAAAAApXLteupHPcbSxbSHkhNTuYLChX'
               ));

                 $validatorSchema['captcha'] = new sfValidatorReCaptcha(array(
                   'private_key' => '6Ld2DgQAAAAAANIbaXJsFEBOyg56CL_ljy3APlPb'
                 ));
             }
         }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                     30
Symfony 1.3 + Doctrine 1.2


 Define formFilterValues() method.
   public function formFilterValues(sfEvent $event, $values)
   {
     $form = $event->getSubject();

       if ($form->reCaptcha)
       {
         $request = sfContext::getInstance()->getRequest();

        $captcha = array(
           'captcha' => array(
             'recaptcha_challenge_field' => $request->getParameter('recaptcha_challenge_field'),
             'recaptcha_response_field' => $request->getParameter('recaptcha_response_field')
           )
        );
        $values = array_merge($values, $captcha);
       }
       return $values;
   }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                                 31
Symfony 1.3 + Doctrine 1.2




    Now to enable recaptcha for
     any of your forms just add a
    public property to your forms
         with a value of true


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   32
Symfony 1.3 + Doctrine 1.2


 Enable recaptcha on MyForm.

 class MyForm extends BaseForm
 {
   public $reCaptcha = true;

     public function configure()
     {
       $this->widgetSchema['title'] = new sfWidgetFormInputText();
       $this->validatorSchema['title'] = new sfValidatorString();

         $this->widgetSchema->setNameFormat('my_form[%s]');
     }
 }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                     33
Symfony 1.3 + Doctrine 1.2




     Now MyForm has recaptcha
     enabled. Enable it on any of
          your other forms.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   34
Symfony 1.3 + Doctrine 1.2




  The previous example requires
    that sfFormExtraPlugin be
     installed in your project.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   35
Symfony 1.3 + Doctrine 1.2




      Of course we could have
     implemented this right in
  BaseForm without events. This
    would make more sense if
    implemented via a plugin.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   36
Symfony 1.3 + Doctrine 1.2




           Testing Improvements




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   37
Symfony 1.3 + Doctrine 1.2




            sfTesterResponse adds
              matches() method



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   38
Symfony 1.3 + Doctrine 1.2




       Runs a regex on the entire
           response content.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   39
Symfony 1.3 + Doctrine 1.2




        $browser->with('response')->begin()->
            matches('/I // it takes d+ apples/')->
$browser->with('response')->begin()->
  matches('/I have d+ apples/')->    have a regex as an argument
  matches('!/I have d+ apples/')->
            matches('!/I// havealso add regex modifiers
                                      // a ! at the beginning means that the regex must not match
  matches('!/I have d+ apples/i')->     you can   d+ apples/')->
end();
            matches('!/I have d+ apples/i')->
        end();




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                                40
Symfony 1.3 + Doctrine 1.2




  More powerful than contains()
  and is useful for non-XML type
         responses where
 checkElement() cannot be used


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   41
Symfony 1.3 + Doctrine 1.2




            Tests now have JUnit
           Compatible XML Output

         $ php symfony test:all --xml=log.xml




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2    42
Symfony 1.3 + Doctrine 1.2




   Output exception traces when
         running all tests

         $ php symfony test:all -t



                       Useful for debugging failing tests



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                43
Symfony 1.3 + Doctrine 1.2




     New checkForm() method on
          sfTesterResponse
            Tests that all form fields are rendered
            properly in the HTML response.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2          44
Symfony 1.3 + Doctrine 1.2




      $browser->with('response')->begin()->
        checkForm('ArticleForm')->
      end();




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   45
Symfony 1.3 + Doctrine 1.2


 Use CSS selectors when dealing with multiple forms




 $browser->with('response')->begin()->
   checkForm('ArticleForm', '#articleForm')->
 end();




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2          46
Symfony 1.3 + Doctrine 1.2




       Improve Developer Testing
              Efficiency



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   47
Symfony 1.3 + Doctrine 1.2




      When you have a large test
     suite it is time consuming to
     run all tests every time you
            make a change.


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   48
Symfony 1.3 + Doctrine 1.2




      Use the --only-failed option




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   49
Symfony 1.3 + Doctrine 1.2




    After you run the test suite
       once, re-run with the
  --only-failed option to execute
   only the failed tests from the
           previous run.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   50
Symfony 1.3 + Doctrine 1.2




    Now you can re-run this over
    and over until you have zero
          failures again.


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   51
Symfony 1.3 + Doctrine 1.2




             Interactive CLI Tasks

  Ask the user for some input and use it
               in your task



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   52
Symfony 1.3 + Doctrine 1.2


 In your task class you can use some code like below.




          $anwser = $this->askAndValidate(
             'What is you email?',
             new sfValidatorEmail()
          );




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2            53
Symfony 1.3 + Doctrine 1.2




 Improved Doctrine Integration




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   54
Symfony 1.3 + Doctrine 1.2




     Disable Form Generation for
            Certain Models



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   55
Symfony 1.3 + Doctrine 1.2
   For models like many to many join tables we don’t need
    form classes so we can disable the generation of them.

                          UserGroup:
                            options:
                              symfony:
                                form: false
                                filter: false
                            columns:
                              user_id:
                                type: integer
                                primary: true
                              group_id:
                                type: integer
                                primary: true



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2             56
Symfony 1.3 + Doctrine 1.2




     Generated forms now follow
     model inheritance hierarchy



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   57
Symfony 1.3 + Doctrine 1.2


      Now your form classes will generate the same
     inheritance structure that your models define.

               class Moderator extends User
               {
                 // ...
               }

               class ModeratorForm extends UserForm
               {
                 // ...
               }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2          58
Symfony 1.3 + Doctrine 1.2




              New Doctrine Tasks




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   59
Symfony 1.3 + Doctrine 1.2




Create Tables for Set of Models
           Task will drop and recreate specified tables.

      $ php symfony doctrine:create-model-tables Model1 Model2 Model3


       Useful in development mode when you want to
       rebuild a set of models in the database over and
       over while you’re working on it. Instead of having
       to rebuild the entire database just to test.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                            60
Symfony 1.3 + Doctrine 1.2




                Delete Model Files
               Delete associated generated files for
               a model like forms and filter classes.

            $ php symfony doctrine:delete-model-files ModelName



     This is useful if you remove a model or rename a
     model, before you would have to manually clean up
     these classes and it was a pain. This task automates
     it for you.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                      61
Symfony 1.3 + Doctrine 1.2




                 Clean Model Files
             This task is combined with the previous
             task to clean up orphaned model files.

                   $ php symfony doctrine:clean-model-files


     It detects what model all model files exist on disk but
     cannot be found in your YAML schema files. It will
     find these files and report them to you asking you to
     confirm whether or not they should be deleted.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                   62
Symfony 1.3 + Doctrine 1.2



                       Reload Data
                     $ php symfony doctrine:reload-data


          The above is the same as doing the following

                     $ php symfony doctrine:drop-db
                     $ php symfony doctrine:build-db
                     $ php symfony doctrine:insert-sql
                     $ php symfony doctrine:data-load


              This is commonly used to prepare a
              test database before each test is run.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2              63
Symfony 1.3 + Doctrine 1.2




              The New Build Task
  The new doctrine:build task allows you to specify what
  exactly you would like symfony and Doctrine to build. This
  task replicates the functionality in many of the existing
  combination-tasks, which have all been deprecated in
  favor of this more flexible solution.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2              64
Symfony 1.3 + Doctrine 1.2



                    Build Examples
                  $ php symfony doctrine:build --db --and-load



            This will drop and create the database,
            create the tables configured in your
            YAML schema and load the fixture data.




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                     65
Symfony 1.3 + Doctrine 1.2



                    Build Examples
            $ php symfony doctrine:build --all-classes --and-migrate




              This will build the model, forms, form
              filters and run any pending migrations.




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                           66
Symfony 1.3 + Doctrine 1.2



                    Build Examples
$ php symfony doctrine:build --model --and-migrate --and-append=data/fixtures/
categories.yml




          This will build the model, migrate the
          database and append category fixtures data.




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                               67
Symfony 1.3 + Doctrine 1.2



    Dealing with Doctrine Dates

  We've added two new methods for retrieving Doctrine
  date/time values as PHP DateTime object instances.




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2            68
Symfony 1.3 + Doctrine 1.2



     If you prefer to work with DateTime objects then you can
      use these methods to get and set your Doctrine date
      values.




    echo $article->getDateTimeObject('created_at')->format('m/d/Y');

    $article->setDateTimeObject('created_at', new DateTime('09/01/1985'));




                www.php.net/DateTime

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                            69
Symfony 1.3 + Doctrine 1.2


Alternative doctrine:dql output
  $ ./symfony doctrine:dql "FROM Article a" --table
  >> doctrine executing dql query
  DQL: FROM Article a
  +----+-----------+----------------+---------------------+---------------------+
  | id | author_id | is_on_homepage | created_at          | updated_at          |
  +----+-----------+----------------+---------------------+---------------------+
  | 1 | 1          |                | 2009-07-07 18:02:24 | 2009-07-07 18:02:24 |
  | 2 | 2          |                | 2009-07-07 18:02:24 | 2009-07-07 18:02:24 |
  +----+-----------+----------------+---------------------+---------------------+
  (2 results)




          You probably recognize this as it is how the
          mysql command line outputs SQL queries.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                   70
Symfony 1.3 + Doctrine 1.2




                       Doctrine 1.2




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   71
Symfony 1.3 + Doctrine 1.2




         Easy to upgrade from 1.1




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   72
Symfony 1.3 + Doctrine 1.2




   Some deprecated functions,
  methods, etc. removed but the
   core of things have remained
    mostly the same. Only new
  features and flexibilities have
            been added.

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   73
Symfony 1.3 + Doctrine 1.2




               Custom Query Class




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   74
Symfony 1.3 + Doctrine 1.2


 Specify the query class to use in your project somewhere
    in your configuration.




      $manager->setAttribute(
         Doctrine::ATTR_QUERY_CLASS,
         'MyQuery'
      );




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                75
Symfony 1.3 + Doctrine 1.2


 Define the MyQuery class which extends Doctrine_Query




       class MyQuery extends Doctrine_Query
       {

       }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2             76
Symfony 1.3 + Doctrine 1.2




 Now you can add new methods
   and override functionality in
 the Doctrine_Query class for all
    your query objects in your
           application

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   77
Symfony 1.3 + Doctrine 1.2




          Custom Collection Class




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   78
Symfony 1.3 + Doctrine 1.2


 Specify the collection class to use in your project
    somewhere in your configuration.



  $manager->setAttribute(
     Doctrine::ATTR_COLLECTION_CLASS,
     'MyCollection'
  );




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2           79
Symfony 1.3 + Doctrine 1.2


 Define the MyCollection class which extends
    Doctrine_Collection




  class MyCollection extends Doctrine_Collection
  {

  }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   80
Symfony 1.3 + Doctrine 1.2




  Now you can add new methods
   and override functionality in
        your collections.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   81
Symfony 1.3 + Doctrine 1.2


 Add new method to get the sum of a field in a collection.


            class MyCollection extends Doctrine_Collection
            {
              public function getSum($field)
              {
                $sum = 0;
                foreach ($this as $record)
                {
                  $sum = $sum + $record->get($field);
                }
                return $sum;
              }
            }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                 82
Symfony 1.3 + Doctrine 1.2


 Now it can be used like the following




  $transactions = Doctrine::getTable('Transaction')
    ->retrieveAllUserTransactions('jwage');

  echo get_class($transactions); // MyCollection

  // Output the total amount billed for all transactions for jwage
  echo $transactions->getSum('total_billed');




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                    83
Symfony 1.3 + Doctrine 1.2




           Custom Data Hydrators




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   84
Symfony 1.3 + Doctrine 1.2




 It is now possible to write and register your own custom
 data hydrators which can be used from your query objects.



   $manager->registerHydrator('MyHydrator', ‘MyHydratorDriver’);




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                       85
Symfony 1.3 + Doctrine 1.2


 Define the MyHydrator class



  class MyHydratorDriver extends Doctrine_Hydrator_Abstract
  {
      public function hydrateResultSet($stmt)
      {
          return $stmt->fetchAll(PDO::FETCH_ASSOC);
      }
  }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2             86
Symfony 1.3 + Doctrine 1.2




  Custom hydrators must extend
   Doctrine_Hydrator_Abstract
     and must implement the
   hydrateResultSet() method.


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   87
Symfony 1.3 + Doctrine 1.2



 The core hydrators execute the
    PDO statement and build a
      special structure to be
  returned. You can execute the
 statement and do whatever you
    want with the data before
           returning it.
Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   88
Symfony 1.3 + Doctrine 1.2



           Using Custom Hydrator


        $q->execute(array(), 'MyHydrator');




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   89
Symfony 1.3 + Doctrine 1.2




       Custom Connection Classes




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   90
Symfony 1.3 + Doctrine 1.2




     Sometimes you may have some
 proprietary database type that Doctrine
      does not support. The custom
   connections allow you to implement
    your own database drivers to use.



Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   91
Symfony 1.3 + Doctrine 1.2



       Register Connection Driver

   $manager->registerConnectionDriver(
     'test', 'Doctrine_Connection_Test'
   );




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   92
Symfony 1.3 + Doctrine 1.2



        Define Connection Classes
 class Doctrine_Connection_Test extends Doctrine_Connection_Common
 {
 }

 class Doctrine_Adapter_Test implements Doctrine_Adapter_Interface
 {
   // ... all the methods defined in the interface
   // ... mimics the PDO interface which connects
   // ... to your database
 }




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                    93
Symfony 1.3 + Doctrine 1.2



           Open a New Connection
  $conn = $manager->openConnection('test://username:password@localhost/dbname');

  echo get_class($conn); // Doctrine_Connection_Test
  echo get_class($conn->getDbh()); // Doctrine_Adapter_Test




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                  94
Symfony 1.3 + Doctrine 1.2




       Improve Save Performance
$manager->setAttribute(Doctrine::ATTR_CASCADE_SAVES, false);


     Disabling cascading saves to improve performance
     when saving lots of objects. The negative affect of
     this change is that you can’t save dirty objects that
     are more than one level deep in the object hierarchy.


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                 95
Symfony 1.3 + Doctrine 1.2




 New Convenience Magic Finders




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   96
Symfony 1.3 + Doctrine 1.2


 Method name is converted in to
 a DQL query. Combine AND/OR
          conditions.
$user = $table->findOneByUsernameAndPassword('jwage', md5('changeme'));
$users = $table->findByIsAdminOrIsModerator(true, true);




   Please be aware these finders are very limited and are
   only meant for quickly prototyping code. It is almost
   always recommended to write your own DQL queries
   which select and join the exact resultset you need.
Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                              97
Symfony 1.3 + Doctrine 1.2




Doctrine Extensions Repository
     With the start of Doctrine 1.2 development we
     opened a special repository for users to contribute
     extensions to Doctrine to share with the community.




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2               98
Symfony 1.3 + Doctrine 1.2



       Similar to Symfony Plugins




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   99
Symfony 1.3 + Doctrine 1.2




             Using the Extensions
   Outside of Symfony Doctrine has a mechanism for
   autoloading and registering extensions. This is not
   necessary in Symfony because the native autoloading
   will load the code for the extension. We just need to
   download the code and put it somewhere in Symfony.


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2               100
Symfony 1.3 + Doctrine 1.2



              Using the Extensions
$ cd /path/to/symfony/project
$ mkdir lib/doctrine_extensions
$ svn co http://svn.doctrine-project.org/extensions/Taggable/branches/1.2-1.0/
Taggable
$ ./symfony cc




Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                101
Symfony 1.3 + Doctrine 1.2


             Using the Extensions
          ---
          Article:
            actAs: [Taggable]
            columns:
              title: string(255)
              body: clob
Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2   102
Symfony 1.3 + Doctrine 1.2

                          Questions?
        Jonathan H. Wage
        jonathan.wage@sensio.com
        +1 415 992 5468

        sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com



You can contact Jonathan about Doctrine and Open-Source or
 for training, consulting, application development, or business
        related questions at jonathan.wage@sensio.com


Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2                                103

More Related Content

What's hot

Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)진성 오
 
Example of JAVA Program
Example of JAVA ProgramExample of JAVA Program
Example of JAVA ProgramTrenton Asbury
 
20180310 functional programming
20180310 functional programming20180310 functional programming
20180310 functional programmingChiwon Song
 
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...ssuserd6b1fd
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developersLuiz Messias
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...ssuserd6b1fd
 
20181020 advanced higher-order function
20181020 advanced higher-order function20181020 advanced higher-order function
20181020 advanced higher-order functionChiwon Song
 
オレオレSecurityバンドル作っちゃいました
オレオレSecurityバンドル作っちゃいましたオレオレSecurityバンドル作っちゃいました
オレオレSecurityバンドル作っちゃいましたKatsuhiro Ogawa
 
20180721 code defragment
20180721 code defragment20180721 code defragment
20180721 code defragmentChiwon Song
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...ssuserd6b1fd
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aidDavid Hoyt
 
Estendere applicazioni extbase
Estendere applicazioni extbaseEstendere applicazioni extbase
Estendere applicazioni extbaseCristian Buja
 
ภาษาซี
ภาษาซีภาษาซี
ภาษาซีkramsri
 
The Effective Developer - Work Smarter, Not Harder
The Effective Developer - Work Smarter, Not HarderThe Effective Developer - Work Smarter, Not Harder
The Effective Developer - Work Smarter, Not HarderSven Peters
 
Twigエクステンションの作り方
Twigエクステンションの作り方Twigエクステンションの作り方
Twigエクステンションの作り方Katsuhiro Ogawa
 

What's hot (20)

Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)Swift에서 꼬리재귀 사용기 (Tail Recursion)
Swift에서 꼬리재귀 사용기 (Tail Recursion)
 
Example of JAVA Program
Example of JAVA ProgramExample of JAVA Program
Example of JAVA Program
 
20180310 functional programming
20180310 functional programming20180310 functional programming
20180310 functional programming
 
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developers
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 2 of 5 by...
 
Clang2018 class3
Clang2018 class3Clang2018 class3
Clang2018 class3
 
Oop lecture9
Oop lecture9Oop lecture9
Oop lecture9
 
20181020 advanced higher-order function
20181020 advanced higher-order function20181020 advanced higher-order function
20181020 advanced higher-order function
 
Csharp_Chap13
Csharp_Chap13Csharp_Chap13
Csharp_Chap13
 
オレオレSecurityバンドル作っちゃいました
オレオレSecurityバンドル作っちゃいましたオレオレSecurityバンドル作っちゃいました
オレオレSecurityバンドル作っちゃいました
 
20180721 code defragment
20180721 code defragment20180721 code defragment
20180721 code defragment
 
Matlab differential
Matlab differentialMatlab differential
Matlab differential
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5  b...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aid
 
My favorite slides
My favorite slidesMy favorite slides
My favorite slides
 
Estendere applicazioni extbase
Estendere applicazioni extbaseEstendere applicazioni extbase
Estendere applicazioni extbase
 
ภาษาซี
ภาษาซีภาษาซี
ภาษาซี
 
The Effective Developer - Work Smarter, Not Harder
The Effective Developer - Work Smarter, Not HarderThe Effective Developer - Work Smarter, Not Harder
The Effective Developer - Work Smarter, Not Harder
 
Twigエクステンションの作り方
Twigエクステンションの作り方Twigエクステンションの作り方
Twigエクステンションの作り方
 

Viewers also liked

Yeşil pazarlama 1.2
Yeşil pazarlama 1.2Yeşil pazarlama 1.2
Yeşil pazarlama 1.2Sezzy Naim
 
özetliyorum.com girişim proje
özetliyorum.com girişim projeözetliyorum.com girişim proje
özetliyorum.com girişim projeAli Emre Süslü
 
Modern Pazarlama Yönetimi ve Pazarlamada Yeni Trendler
Modern Pazarlama Yönetimi ve Pazarlamada Yeni TrendlerModern Pazarlama Yönetimi ve Pazarlamada Yeni Trendler
Modern Pazarlama Yönetimi ve Pazarlamada Yeni TrendlerAhmet Yılmaz
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHPRob Knight
 
Doctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmDoctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmJonathan Wage
 

Viewers also liked (7)

Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 
What Is Doctrine?
What Is Doctrine?What Is Doctrine?
What Is Doctrine?
 
Yeşil pazarlama 1.2
Yeşil pazarlama 1.2Yeşil pazarlama 1.2
Yeşil pazarlama 1.2
 
özetliyorum.com girişim proje
özetliyorum.com girişim projeözetliyorum.com girişim proje
özetliyorum.com girişim proje
 
Modern Pazarlama Yönetimi ve Pazarlamada Yeni Trendler
Modern Pazarlama Yönetimi ve Pazarlamada Yeni TrendlerModern Pazarlama Yönetimi ve Pazarlamada Yeni Trendler
Modern Pazarlama Yönetimi ve Pazarlamada Yeni Trendler
 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHP
 
Doctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php OrmDoctrine 2 - Not The Same Old Php Orm
Doctrine 2 - Not The Same Old Php Orm
 

Similar to Symfony 1.3 + Doctrine 1.2

Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Jakub Zalas
 
A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014Matthias Noback
 
Symfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusSymfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusIgnacio Martín
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Fabien Potencier
 
The Ring programming language version 1.3 book - Part 18 of 88
The Ring programming language version 1.3 book - Part 18 of 88The Ring programming language version 1.3 book - Part 18 of 88
The Ring programming language version 1.3 book - Part 18 of 88Mahmoud Samir Fayed
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)Javier Eguiluz
 
Working With The Symfony Admin Generator
Working With The Symfony Admin GeneratorWorking With The Symfony Admin Generator
Working With The Symfony Admin GeneratorJohn Cleveley
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014Matthias Noback
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018Юлия Коваленко
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
Creating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdfCreating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdfShaiAlmog1
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189Mahmoud Samir Fayed
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfudit652068
 
Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)Fabien Potencier
 

Similar to Symfony 1.3 + Doctrine 1.2 (20)

Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014
 
Symfony 4 Workshop - Limenius
Symfony 4 Workshop - LimeniusSymfony 4 Workshop - Limenius
Symfony 4 Workshop - Limenius
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)Symfony 2 (PHP Quebec 2009)
Symfony 2 (PHP Quebec 2009)
 
The Ring programming language version 1.3 book - Part 18 of 88
The Ring programming language version 1.3 book - Part 18 of 88The Ring programming language version 1.3 book - Part 18 of 88
The Ring programming language version 1.3 book - Part 18 of 88
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
Working With The Symfony Admin Generator
Working With The Symfony Admin GeneratorWorking With The Symfony Admin Generator
Working With The Symfony Admin Generator
 
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014
 
Python for Beginners(v2)
Python for Beginners(v2)Python for Beginners(v2)
Python for Beginners(v2)
 
Managing Mocks
Managing MocksManaging Mocks
Managing Mocks
 
Introducing to Asynchronous Programming
Introducing to Asynchronous  ProgrammingIntroducing to Asynchronous  Programming
Introducing to Asynchronous Programming
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Symfony 4 & Flex news
Symfony 4 & Flex newsSymfony 4 & Flex news
Symfony 4 & Flex news
 
Creating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdfCreating a Facebook Clone - Part XLVI - Transcript.pdf
Creating a Facebook Clone - Part XLVI - Transcript.pdf
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
 
Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)Symfony As A Platform (Symfony Camp 2007)
Symfony As A Platform (Symfony Camp 2007)
 

More from Jonathan Wage

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
OpenSky Infrastructure
OpenSky InfrastructureOpenSky Infrastructure
OpenSky InfrastructureJonathan Wage
 
Doctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisDoctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisJonathan Wage
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
Doctrine in the Real World
Doctrine in the Real WorldDoctrine in the Real World
Doctrine in the Real WorldJonathan Wage
 
ZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMJonathan Wage
 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectJonathan Wage
 
Symfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMSymfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMJonathan Wage
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperJonathan Wage
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationJonathan Wage
 
Doctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHPDoctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHPJonathan Wage
 
Introduction To Doctrine 2
Introduction To Doctrine 2Introduction To Doctrine 2
Introduction To Doctrine 2Jonathan Wage
 
Doctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPDoctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPJonathan Wage
 
Sympal A Cmf Based On Symfony
Sympal   A Cmf Based On SymfonySympal   A Cmf Based On Symfony
Sympal A Cmf Based On SymfonyJonathan Wage
 
Sympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMSSympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMSJonathan Wage
 
What's new in Doctrine
What's new in DoctrineWhat's new in Doctrine
What's new in DoctrineJonathan Wage
 
Sympal - Symfony CMS Preview
Sympal - Symfony CMS PreviewSympal - Symfony CMS Preview
Sympal - Symfony CMS PreviewJonathan Wage
 
Doctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperDoctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperJonathan Wage
 
Sympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony CmsSympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony CmsJonathan Wage
 

More from Jonathan Wage (20)

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
OpenSky Infrastructure
OpenSky InfrastructureOpenSky Infrastructure
OpenSky Infrastructure
 
Doctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisDoctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 Paris
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Doctrine in the Real World
Doctrine in the Real WorldDoctrine in the Real World
Doctrine in the Real World
 
ZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODM
 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine Project
 
Symfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMSymfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODM
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document Mapper
 
Libertyvasion2010
Libertyvasion2010Libertyvasion2010
Libertyvasion2010
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 Integration
 
Doctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHPDoctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHP
 
Introduction To Doctrine 2
Introduction To Doctrine 2Introduction To Doctrine 2
Introduction To Doctrine 2
 
Doctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPDoctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHP
 
Sympal A Cmf Based On Symfony
Sympal   A Cmf Based On SymfonySympal   A Cmf Based On Symfony
Sympal A Cmf Based On Symfony
 
Sympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMSSympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMS
 
What's new in Doctrine
What's new in DoctrineWhat's new in Doctrine
What's new in Doctrine
 
Sympal - Symfony CMS Preview
Sympal - Symfony CMS PreviewSympal - Symfony CMS Preview
Sympal - Symfony CMS Preview
 
Doctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperDoctrine Php Object Relational Mapper
Doctrine Php Object Relational Mapper
 
Sympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony CmsSympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony Cms
 

Recently uploaded

Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfngoud9212
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 

Recently uploaded (20)

Bluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdfBluetooth Controlled Car with Arduino.pdf
Bluetooth Controlled Car with Arduino.pdf
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 

Symfony 1.3 + Doctrine 1.2

  • 1. Symfony 1.3 + Doctrine 1.2 Symfony 1.3 + Doctrine 1.2 Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 1
  • 2. Symfony 1.3 + Doctrine 1.2 Continued Evolution of Symfony 1.x Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 2
  • 3. Symfony 1.3 + Doctrine 1.2 Lots of new features, enhancements and bug fixes. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 3
  • 4. Symfony 1.3 + Doctrine 1.2 Out with the old and in with the new! Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 4
  • 5. Symfony 1.3 + Doctrine 1.2 Doctrine is the default ORM Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 5
  • 6. Symfony 1.3 + Doctrine 1.2 Propel is deprecated Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 6
  • 7. Symfony 1.3 + Doctrine 1.2 Propel is deprecated in 1.3 but not removed. It will be dropped completely in symfony 2.0 Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 7
  • 8. Symfony 1.3 + Doctrine 1.2 Still want to use Propel? :) Generate your project with the new --orm option $ php /path/to/symfony generate:project foo --orm=Propel Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 8
  • 9. Symfony 1.3 + Doctrine 1.2 New Symfony Features Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 9
  • 10. Symfony 1.3 + Doctrine 1.2 Use the --installer option to execute Symfony installer scripts Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 10
  • 11. Symfony 1.3 + Doctrine 1.2 $ php /path/to/symfony generate:project --installer=my_installer.php Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 11
  • 12. Symfony 1.3 + Doctrine 1.2 Now in your my_installer.php you can do things like... if (!$this->askConfirmation('Are you sure you want to run this installer?')) { return; } $this->installDir(dirname(__FILE__).'/skeleton'); $this->runTask('plugin:publish-assets'); $validator = new sfValidatorEmail(array(), array('invalid' => 'hmmm, it does not look like an email!')); $email = $this->askAndValidate('Please, give me your email:', $validator); $this->runTask('configure:author', sprintf("'%s'", $email)); $secret = $this->ask('Give a unique string for the CSRF secret:'); $this->runTask('generate:app', 'frontend --escaping-strategy=true --csrf-secret='. $secret); $this->runTask('plugin:install', 'sfDoctrineGuardPlugin'); $this->reloadTasks(); $this->runTask('guard:create-user', 'jwage changeme'); $this->runTask('cache:clear'); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 12
  • 13. Symfony 1.3 + Doctrine 1.2 It replaces the need to maintain your own skeleton symfony project. Just write your own custom installer to generate a new project the way you want it. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 13
  • 14. Symfony 1.3 + Doctrine 1.2 Form Framework Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 14
  • 15. Symfony 1.3 + Doctrine 1.2 Recognize this? class LoginForm extends BaseUserForm { public function configure() { unset( $this['first_name'], $this['last_name'], $this['email_address'] ); } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 15
  • 16. Symfony 1.3 + Doctrine 1.2 Using unset() to remove fields Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 16
  • 17. Symfony 1.3 + Doctrine 1.2 Instead, lets say what form fields we WANT to use instead of the ones we don’t want Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 17
  • 18. Symfony 1.3 + Doctrine 1.2 Now it is possible with the useFields() method. class LoginForm extends BaseUserForm { public function configure() { $this->useFields(array( 'username', 'password' )); } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 18
  • 19. Symfony 1.3 + Doctrine 1.2 Easier to maintain Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 19
  • 20. Symfony 1.3 + Doctrine 1.2 Does not require keeping unset() list updated when we add new fields to model Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 20
  • 21. Symfony 1.3 + Doctrine 1.2 Forms + Events Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 21
  • 22. Symfony 1.3 + Doctrine 1.2 We now have a sfFormSymfony in core and BaseForm class in each project. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 22
  • 23. Symfony 1.3 + Doctrine 1.2 Sits on top of the agnostic sfForm and couples symfony dispatcher with the form framework. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 23
  • 24. Symfony 1.3 + Doctrine 1.2 Allows us to dispatch symfony events from within the form framework. YES! Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 24
  • 25. Symfony 1.3 + Doctrine 1.2 What events can I use? Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 25
  • 26. Symfony 1.3 + Doctrine 1.2 • form.post_configure - Notified after every form is configured • form.filter_values - Filters tainted parameters and files array just prior to binding • form.validation_error - Notified whenever form validation fails. • form.method_not_found - Notified whenever an unknown method is called Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 26
  • 27. Symfony 1.3 + Doctrine 1.2 Example Form Event Add easy ReCaptcha functionality to all forms Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 27
  • 28. Symfony 1.3 + Doctrine 1.2 Define a regular form that extends sfFormSymfony class MyForm extends BaseForm { public function configure() { $this->widgetSchema['title'] = new sfWidgetFormInputText(); $this->validatorSchema['title'] = new sfValidatorString(); $this->widgetSchema->setNameFormat('my_form[%s]'); } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 28
  • 29. Symfony 1.3 + Doctrine 1.2 Connect events form.post_configure and form.filter_values class ProjectConfiguration extends sfProjectConfiguration { public function setup() { // ... $this->dispatcher->connect('form.post_configure', array( $this, 'formPostConfigure' )); $this->dispatcher->connect('form.filter_values', array( $this, 'formFilterValues' )); } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 29
  • 30. Symfony 1.3 + Doctrine 1.2 Define formPostConfigure() method. public function formPostConfigure(sfEvent $event) { $form = $event->getSubject(); if ($form->reCaptcha) { $widgetSchema = $form->getWidgetSchema(); $validatorSchema = $form->getValidatorSchema(); $widgetSchema['captcha'] = new sfWidgetFormReCaptcha(array( 'public_key' => '6Ld2DgQAAAAAAApXLteupHPcbSxbSHkhNTuYLChX' )); $validatorSchema['captcha'] = new sfValidatorReCaptcha(array( 'private_key' => '6Ld2DgQAAAAAANIbaXJsFEBOyg56CL_ljy3APlPb' )); } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 30
  • 31. Symfony 1.3 + Doctrine 1.2 Define formFilterValues() method. public function formFilterValues(sfEvent $event, $values) { $form = $event->getSubject(); if ($form->reCaptcha) { $request = sfContext::getInstance()->getRequest(); $captcha = array( 'captcha' => array( 'recaptcha_challenge_field' => $request->getParameter('recaptcha_challenge_field'), 'recaptcha_response_field' => $request->getParameter('recaptcha_response_field') ) ); $values = array_merge($values, $captcha); } return $values; } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 31
  • 32. Symfony 1.3 + Doctrine 1.2 Now to enable recaptcha for any of your forms just add a public property to your forms with a value of true Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 32
  • 33. Symfony 1.3 + Doctrine 1.2 Enable recaptcha on MyForm. class MyForm extends BaseForm { public $reCaptcha = true; public function configure() { $this->widgetSchema['title'] = new sfWidgetFormInputText(); $this->validatorSchema['title'] = new sfValidatorString(); $this->widgetSchema->setNameFormat('my_form[%s]'); } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 33
  • 34. Symfony 1.3 + Doctrine 1.2 Now MyForm has recaptcha enabled. Enable it on any of your other forms. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 34
  • 35. Symfony 1.3 + Doctrine 1.2 The previous example requires that sfFormExtraPlugin be installed in your project. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 35
  • 36. Symfony 1.3 + Doctrine 1.2 Of course we could have implemented this right in BaseForm without events. This would make more sense if implemented via a plugin. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 36
  • 37. Symfony 1.3 + Doctrine 1.2 Testing Improvements Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 37
  • 38. Symfony 1.3 + Doctrine 1.2 sfTesterResponse adds matches() method Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 38
  • 39. Symfony 1.3 + Doctrine 1.2 Runs a regex on the entire response content. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 39
  • 40. Symfony 1.3 + Doctrine 1.2 $browser->with('response')->begin()-> matches('/I // it takes d+ apples/')-> $browser->with('response')->begin()-> matches('/I have d+ apples/')-> have a regex as an argument matches('!/I have d+ apples/')-> matches('!/I// havealso add regex modifiers // a ! at the beginning means that the regex must not match matches('!/I have d+ apples/i')-> you can d+ apples/')-> end(); matches('!/I have d+ apples/i')-> end(); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 40
  • 41. Symfony 1.3 + Doctrine 1.2 More powerful than contains() and is useful for non-XML type responses where checkElement() cannot be used Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 41
  • 42. Symfony 1.3 + Doctrine 1.2 Tests now have JUnit Compatible XML Output $ php symfony test:all --xml=log.xml Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 42
  • 43. Symfony 1.3 + Doctrine 1.2 Output exception traces when running all tests $ php symfony test:all -t Useful for debugging failing tests Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 43
  • 44. Symfony 1.3 + Doctrine 1.2 New checkForm() method on sfTesterResponse Tests that all form fields are rendered properly in the HTML response. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 44
  • 45. Symfony 1.3 + Doctrine 1.2 $browser->with('response')->begin()-> checkForm('ArticleForm')-> end(); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 45
  • 46. Symfony 1.3 + Doctrine 1.2 Use CSS selectors when dealing with multiple forms $browser->with('response')->begin()-> checkForm('ArticleForm', '#articleForm')-> end(); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 46
  • 47. Symfony 1.3 + Doctrine 1.2 Improve Developer Testing Efficiency Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 47
  • 48. Symfony 1.3 + Doctrine 1.2 When you have a large test suite it is time consuming to run all tests every time you make a change. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 48
  • 49. Symfony 1.3 + Doctrine 1.2 Use the --only-failed option Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 49
  • 50. Symfony 1.3 + Doctrine 1.2 After you run the test suite once, re-run with the --only-failed option to execute only the failed tests from the previous run. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 50
  • 51. Symfony 1.3 + Doctrine 1.2 Now you can re-run this over and over until you have zero failures again. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 51
  • 52. Symfony 1.3 + Doctrine 1.2 Interactive CLI Tasks Ask the user for some input and use it in your task Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 52
  • 53. Symfony 1.3 + Doctrine 1.2 In your task class you can use some code like below. $anwser = $this->askAndValidate( 'What is you email?', new sfValidatorEmail() ); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 53
  • 54. Symfony 1.3 + Doctrine 1.2 Improved Doctrine Integration Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 54
  • 55. Symfony 1.3 + Doctrine 1.2 Disable Form Generation for Certain Models Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 55
  • 56. Symfony 1.3 + Doctrine 1.2 For models like many to many join tables we don’t need form classes so we can disable the generation of them. UserGroup: options: symfony: form: false filter: false columns: user_id: type: integer primary: true group_id: type: integer primary: true Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 56
  • 57. Symfony 1.3 + Doctrine 1.2 Generated forms now follow model inheritance hierarchy Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 57
  • 58. Symfony 1.3 + Doctrine 1.2 Now your form classes will generate the same inheritance structure that your models define. class Moderator extends User { // ... } class ModeratorForm extends UserForm { // ... } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 58
  • 59. Symfony 1.3 + Doctrine 1.2 New Doctrine Tasks Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 59
  • 60. Symfony 1.3 + Doctrine 1.2 Create Tables for Set of Models Task will drop and recreate specified tables. $ php symfony doctrine:create-model-tables Model1 Model2 Model3 Useful in development mode when you want to rebuild a set of models in the database over and over while you’re working on it. Instead of having to rebuild the entire database just to test. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 60
  • 61. Symfony 1.3 + Doctrine 1.2 Delete Model Files Delete associated generated files for a model like forms and filter classes. $ php symfony doctrine:delete-model-files ModelName This is useful if you remove a model or rename a model, before you would have to manually clean up these classes and it was a pain. This task automates it for you. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 61
  • 62. Symfony 1.3 + Doctrine 1.2 Clean Model Files This task is combined with the previous task to clean up orphaned model files. $ php symfony doctrine:clean-model-files It detects what model all model files exist on disk but cannot be found in your YAML schema files. It will find these files and report them to you asking you to confirm whether or not they should be deleted. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 62
  • 63. Symfony 1.3 + Doctrine 1.2 Reload Data $ php symfony doctrine:reload-data The above is the same as doing the following $ php symfony doctrine:drop-db $ php symfony doctrine:build-db $ php symfony doctrine:insert-sql $ php symfony doctrine:data-load This is commonly used to prepare a test database before each test is run. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 63
  • 64. Symfony 1.3 + Doctrine 1.2 The New Build Task The new doctrine:build task allows you to specify what exactly you would like symfony and Doctrine to build. This task replicates the functionality in many of the existing combination-tasks, which have all been deprecated in favor of this more flexible solution. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 64
  • 65. Symfony 1.3 + Doctrine 1.2 Build Examples $ php symfony doctrine:build --db --and-load This will drop and create the database, create the tables configured in your YAML schema and load the fixture data. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 65
  • 66. Symfony 1.3 + Doctrine 1.2 Build Examples $ php symfony doctrine:build --all-classes --and-migrate This will build the model, forms, form filters and run any pending migrations. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 66
  • 67. Symfony 1.3 + Doctrine 1.2 Build Examples $ php symfony doctrine:build --model --and-migrate --and-append=data/fixtures/ categories.yml This will build the model, migrate the database and append category fixtures data. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 67
  • 68. Symfony 1.3 + Doctrine 1.2 Dealing with Doctrine Dates We've added two new methods for retrieving Doctrine date/time values as PHP DateTime object instances. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 68
  • 69. Symfony 1.3 + Doctrine 1.2 If you prefer to work with DateTime objects then you can use these methods to get and set your Doctrine date values. echo $article->getDateTimeObject('created_at')->format('m/d/Y'); $article->setDateTimeObject('created_at', new DateTime('09/01/1985')); www.php.net/DateTime Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 69
  • 70. Symfony 1.3 + Doctrine 1.2 Alternative doctrine:dql output $ ./symfony doctrine:dql "FROM Article a" --table >> doctrine executing dql query DQL: FROM Article a +----+-----------+----------------+---------------------+---------------------+ | id | author_id | is_on_homepage | created_at | updated_at | +----+-----------+----------------+---------------------+---------------------+ | 1 | 1 | | 2009-07-07 18:02:24 | 2009-07-07 18:02:24 | | 2 | 2 | | 2009-07-07 18:02:24 | 2009-07-07 18:02:24 | +----+-----------+----------------+---------------------+---------------------+ (2 results) You probably recognize this as it is how the mysql command line outputs SQL queries. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 70
  • 71. Symfony 1.3 + Doctrine 1.2 Doctrine 1.2 Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 71
  • 72. Symfony 1.3 + Doctrine 1.2 Easy to upgrade from 1.1 Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 72
  • 73. Symfony 1.3 + Doctrine 1.2 Some deprecated functions, methods, etc. removed but the core of things have remained mostly the same. Only new features and flexibilities have been added. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 73
  • 74. Symfony 1.3 + Doctrine 1.2 Custom Query Class Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 74
  • 75. Symfony 1.3 + Doctrine 1.2 Specify the query class to use in your project somewhere in your configuration. $manager->setAttribute( Doctrine::ATTR_QUERY_CLASS, 'MyQuery' ); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 75
  • 76. Symfony 1.3 + Doctrine 1.2 Define the MyQuery class which extends Doctrine_Query class MyQuery extends Doctrine_Query { } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 76
  • 77. Symfony 1.3 + Doctrine 1.2 Now you can add new methods and override functionality in the Doctrine_Query class for all your query objects in your application Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 77
  • 78. Symfony 1.3 + Doctrine 1.2 Custom Collection Class Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 78
  • 79. Symfony 1.3 + Doctrine 1.2 Specify the collection class to use in your project somewhere in your configuration. $manager->setAttribute( Doctrine::ATTR_COLLECTION_CLASS, 'MyCollection' ); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 79
  • 80. Symfony 1.3 + Doctrine 1.2 Define the MyCollection class which extends Doctrine_Collection class MyCollection extends Doctrine_Collection { } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 80
  • 81. Symfony 1.3 + Doctrine 1.2 Now you can add new methods and override functionality in your collections. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 81
  • 82. Symfony 1.3 + Doctrine 1.2 Add new method to get the sum of a field in a collection. class MyCollection extends Doctrine_Collection { public function getSum($field) { $sum = 0; foreach ($this as $record) { $sum = $sum + $record->get($field); } return $sum; } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 82
  • 83. Symfony 1.3 + Doctrine 1.2 Now it can be used like the following $transactions = Doctrine::getTable('Transaction') ->retrieveAllUserTransactions('jwage'); echo get_class($transactions); // MyCollection // Output the total amount billed for all transactions for jwage echo $transactions->getSum('total_billed'); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 83
  • 84. Symfony 1.3 + Doctrine 1.2 Custom Data Hydrators Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 84
  • 85. Symfony 1.3 + Doctrine 1.2 It is now possible to write and register your own custom data hydrators which can be used from your query objects. $manager->registerHydrator('MyHydrator', ‘MyHydratorDriver’); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 85
  • 86. Symfony 1.3 + Doctrine 1.2 Define the MyHydrator class class MyHydratorDriver extends Doctrine_Hydrator_Abstract { public function hydrateResultSet($stmt) { return $stmt->fetchAll(PDO::FETCH_ASSOC); } } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 86
  • 87. Symfony 1.3 + Doctrine 1.2 Custom hydrators must extend Doctrine_Hydrator_Abstract and must implement the hydrateResultSet() method. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 87
  • 88. Symfony 1.3 + Doctrine 1.2 The core hydrators execute the PDO statement and build a special structure to be returned. You can execute the statement and do whatever you want with the data before returning it. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 88
  • 89. Symfony 1.3 + Doctrine 1.2 Using Custom Hydrator $q->execute(array(), 'MyHydrator'); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 89
  • 90. Symfony 1.3 + Doctrine 1.2 Custom Connection Classes Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 90
  • 91. Symfony 1.3 + Doctrine 1.2 Sometimes you may have some proprietary database type that Doctrine does not support. The custom connections allow you to implement your own database drivers to use. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 91
  • 92. Symfony 1.3 + Doctrine 1.2 Register Connection Driver $manager->registerConnectionDriver( 'test', 'Doctrine_Connection_Test' ); Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 92
  • 93. Symfony 1.3 + Doctrine 1.2 Define Connection Classes class Doctrine_Connection_Test extends Doctrine_Connection_Common { } class Doctrine_Adapter_Test implements Doctrine_Adapter_Interface { // ... all the methods defined in the interface // ... mimics the PDO interface which connects // ... to your database } Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 93
  • 94. Symfony 1.3 + Doctrine 1.2 Open a New Connection $conn = $manager->openConnection('test://username:password@localhost/dbname'); echo get_class($conn); // Doctrine_Connection_Test echo get_class($conn->getDbh()); // Doctrine_Adapter_Test Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 94
  • 95. Symfony 1.3 + Doctrine 1.2 Improve Save Performance $manager->setAttribute(Doctrine::ATTR_CASCADE_SAVES, false); Disabling cascading saves to improve performance when saving lots of objects. The negative affect of this change is that you can’t save dirty objects that are more than one level deep in the object hierarchy. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 95
  • 96. Symfony 1.3 + Doctrine 1.2 New Convenience Magic Finders Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 96
  • 97. Symfony 1.3 + Doctrine 1.2 Method name is converted in to a DQL query. Combine AND/OR conditions. $user = $table->findOneByUsernameAndPassword('jwage', md5('changeme')); $users = $table->findByIsAdminOrIsModerator(true, true); Please be aware these finders are very limited and are only meant for quickly prototyping code. It is almost always recommended to write your own DQL queries which select and join the exact resultset you need. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 97
  • 98. Symfony 1.3 + Doctrine 1.2 Doctrine Extensions Repository With the start of Doctrine 1.2 development we opened a special repository for users to contribute extensions to Doctrine to share with the community. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 98
  • 99. Symfony 1.3 + Doctrine 1.2 Similar to Symfony Plugins Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 99
  • 100. Symfony 1.3 + Doctrine 1.2 Using the Extensions Outside of Symfony Doctrine has a mechanism for autoloading and registering extensions. This is not necessary in Symfony because the native autoloading will load the code for the extension. We just need to download the code and put it somewhere in Symfony. Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 100
  • 101. Symfony 1.3 + Doctrine 1.2 Using the Extensions $ cd /path/to/symfony/project $ mkdir lib/doctrine_extensions $ svn co http://svn.doctrine-project.org/extensions/Taggable/branches/1.2-1.0/ Taggable $ ./symfony cc Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 101
  • 102. Symfony 1.3 + Doctrine 1.2 Using the Extensions --- Article: actAs: [Taggable] columns: title: string(255) body: clob Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 102
  • 103. Symfony 1.3 + Doctrine 1.2 Questions? Jonathan H. Wage jonathan.wage@sensio.com +1 415 992 5468 sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com You can contact Jonathan about Doctrine and Open-Source or for training, consulting, application development, or business related questions at jonathan.wage@sensio.com Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 103