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