Symfony 1.3 + Doctrine 1.2

Post on 06-May-2015

21493 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Presentation on Symfony 1.3 and Doctrine 1.2 for Symfony Day Cologne 2009.

Transcript

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: 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 2

Continued Evolutionof Symfony 1.x

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 3

Lots of new features, enhancements and bug fixes.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 4

Out with the old and in with the new!

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 5

Doctrine is the default ORM

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 6

Propel is deprecated

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 7

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

completely in symfony 2.0

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 8

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

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 9

New Symfony Features

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 10

Use the --installer option to execute Symfony installer

scripts

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 11

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 12

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');

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 13

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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 14

Form Framework

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 15

Recognize this?

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 16

Using unset() to remove fields

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 17

Instead, lets say what form fields we WANT to use instead

of the ones we don’t want

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 18

Now it is possible with the useFields() method.

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 19

Easier to maintain

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 20

Does not require keeping unset() list updated when we

add new fields to model

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 21

Forms + Events

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 22

We now have a sfFormSymfony in core and BaseForm class in

each project.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 23

Sits on top of the agnostic sfForm and couples symfony

dispatcher with the form framework.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 24

Allows us to dispatch symfony events from within the form

framework. YES!

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 25

What events can I use?

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 26

• 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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 27

Example Form Event

Add easy ReCaptcha functionality to all forms

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 28

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]'); }}

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 29

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' )); }}

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 30

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' )); } }

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 31

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; }

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 32

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

with a value of true

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 33

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]'); }}

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 34

Now MyForm has recaptcha enabled. Enable it on any of

your other forms.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 35

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 36

Of course we could have implemented this right in

BaseForm without events. This would make more sense if implemented via a plugin.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 37

Testing Improvements

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 38

sfTesterResponse adds matches() method

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 39

Runs a regex on the entire response content.

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 40

$browser->with('response')->begin()-> matches('/I have \d+ apples/')-> matches('!/I have \d+ apples/')-> matches('!/I have \d+ apples/i')->end();

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 41

More powerful than contains() and is useful for non-XML type

responses where checkElement() cannot be used

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2

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

42

Tests now have JUnit Compatible XML Output

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 43

$ php symfony test:all -t

Output exception traces when running all tests

Useful for debugging failing tests

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 44

New checkForm() method on sfTesterResponse

Tests that all form fields are rendered properly in the HTML response.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 45

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 46

Use CSS selectors when dealing with multiple forms

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 47

Improve Developer Testing Efficiency

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 48

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

make a change.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 49

Use the --only-failed option

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 50

After you run the test suite once, re-run with the

--only-failed option to execute only the failed tests from the

previous run.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 51

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

failures again.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 52

Interactive CLI Tasks

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 53

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

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 54

Improved Doctrine Integration

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 55

Disable Form Generation for Certain Models

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 56

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 57

Generated forms now follow model inheritance hierarchy

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 58

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

class Moderator extends User{ // ...}

class ModeratorForm extends UserForm{ // ...}

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 59

New Doctrine Tasks

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 60

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

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

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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 61

Delete Model FilesDelete 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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 62

Clean Model FilesThis 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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 63

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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 64

The New Build TaskThe 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.

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 65

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

Build Examples

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 66

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

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

Build Examples

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 67

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

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

Build Examples

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 68

Dealing with Doctrine Dates

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 69

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 70

Alternative doctrine:dql output

$ ./symfony doctrine:dql "FROM Article a" --table>> doctrine executing dql queryDQL: 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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 71

Doctrine 1.2

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 72

Easy to upgrade from 1.1

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 73

Some deprecated functions, methods, etc. removed but the core of things have remained mostly the same. Only new

features and flexibilities have been added.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 74

Custom Query Class

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 75

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

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 76

Define the MyQuery class which extends Doctrine_Query

class MyQuery extends Doctrine_Query{ }

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 77

Now you can add new methods and override functionality in

the Doctrine_Query class for all your query objects in your

application

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 78

Custom Collection Class

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 79

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

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 80

Define the MyCollection class which extends Doctrine_Collection

class MyCollection extends Doctrine_Collection{ }

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 81

Now you can add new methods and override functionality in

your collections.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 82

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; }}

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 83

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 jwageecho $transactions->getSum('total_billed');

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 84

Custom Data Hydrators

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 85

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’);

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 86

Define the MyHydrator class

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 87

Custom hydrators must extend Doctrine_Hydrator_Abstract

and must implement thehydrateResultSet() method.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 88

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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 89

Using Custom Hydrator

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 90

Custom Connection Classes

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 91

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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 92

Register Connection Driver

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 93

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}

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 94

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

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

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 95

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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 96

New Convenience Magic Finders

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 97

$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.

Method name is converted in to a DQL query. Combine AND/OR

conditions.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 98

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.

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 99

Similar to Symfony Plugins

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 100

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.

Using the Extensions

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 101

$ 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

Using the Extensions

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 102

Using the Extensions

---Article: actAs: [Taggable] columns: title: string(255) body: clob

Symfony 1.3 + Doctrine 1.2

Jonathan H. Wage: Symfony 1.3 + Doctrine 1.2 103

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. Wagejonathan.wage@sensio.com+1 415 992 5468

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

Questions?

top related