doctrine cheat sheet / ullright code conventions
Introduction
Doctrine provides many equal ways to do queries. To be consistent troughout ullright we aim to use only the following "styles".
Schema
Default path: config/doctrine/mySchema.yml
For plugins: plugins/myPlugin/config/doctrine/mySchema.yml
Example schema for a plugin
(Note the "package" path, which builds the models to plugins/myPlugin/lib/model/doctrine/)
UllUser: package: ullCorePlugin.lib.model.doctrine columns: name: type: string(64) location_id: type: integer type: type: enum values: [dumb, bright] default: bright notnull: true description: type: string(4000) # results in a MySQL "text" field type birthday: type: date active: type: boolean default: true updated_at: type: timestamp some_unique_stuff: type: integer notnull: true indexes: some_unique_stuff_index: fields: [some_unique_stuff] type: unique Phonenumber: columns: number: type: string(128) ull_user_id: type: integer relations: UllUser: # When a user is deleted all phonenumbers are deleted as well onDelete: CASCADE #m:n unique UllUserGroup: columns: ull_user_id: type: integer notnull: true ull_group_id: type: integer notnull: true indexes: ull_user_group_unique: fields: [ 'ull_user_id', 'ull_group_id'] type: unique
Always assign a default value (true or false) to booleans whenever possible. Reason: if you set nothing, "null" is used which is not catched by $q->addWhere('my_boolean = ?', false)
String lengths with MySql
string(>=255) - TINYTEXT 256 bytes
string(>65536) - TEXT 65,535 bytes ~64kb
??? - MEDIUMTEXT 16,777,215 bytes ~16MB
clob - LONGTEXT 4,294,967,295 bytes ~4GB
Queries
Shortcuts using Doctrine::getTable()
Find all
$users = Doctrine::getTable('User')->findAll(); echo $users->getFirst()->username;
Find by Id
$user = Doctrine::getTable('User')->find(1); echo $user->username;
Find by any field
$users = Doctrine::getTable('User')->findByFirstName('Klemens'); echo $users->getFirst()->username;
Find one by any field
$user = Doctrine::getTable('User')->findOneByFirstName('Klemens'); echo $user->username;
Note: "findByFirstName()" etc are magic methods.
Custom Finders
Are usually put into PluginUllXxxTable.class.php
If one of the global Doctrine::getTable() finders is overwritten, it must return a compatible output.
If cashing is used the convention is e.g. findOneByEmailCached()
Full DQL
Defining the query:
$q = new Doctrine_Query; $q ->select('u.name, u.email') ->from('User u') ->where('u.country = ?', $country) ; $users = $q->execute();
Index by:
->from('User u INDEXBY u.username');
Conditional Join
$q ->from('UllUser u') ->leftJoin('u.UllEntityGroup ep WITH ep.ull_group_id = ?', 123) ;
Order by with MySQL "IFNULL"
$q ->from('UllEntityGroup ep') // convert NULL to a high integer. therefore NULL entries are ordered last ->select('IFNULL(ep.position, 999999999) as postition_int'); ->addOrderBy('postition_int asc') ;
Fetch as array:
$users = $q->fetchArray();
Fetch the first record only:
$user = $q->fetchOne();
Get value:
$name = $user->name;
Custom hydration option
$users = $q->execute(array(), Doctrine::HYDRATE_NONE)
Set current date
$user->date = new Doctrine_Expression('NOW()');
Single scalar $q = new Doctrine_Query(); $q ->select('name') ->from('UllDepartment') ->orderBy('name') ; $result = $q->execute(array(), Doctrine::HYDRATE_SINGLE_SCALAR); array (size=3) 0 (length=6) 1 (length=5) 2 (length=13)
Delete
Example for many to many:
$q = new Doctrine_Query; $q ->delete('ParentChild pc') ->where('pc.parent_ull_user_id = ?', $parent_ull_user_id) ->addWhere('pc.child_ull_user_id = ?', $child_ull_user_id) ; $q->execute();
Hydration
You should always use array hydration when you only need data for access-only purposes, whereas you should use the
record hydration when you need to change the fetched data.
Debug query:
var_dump($q->getSql()); var_dump($q->getParams());
Update:
$q = new Doctrine_Query; $q ->update('I18nMsgTransUnit t') ->set('t.target', '?', $target) ->set('t.comments', '?', $comments) ->set('t.date_modified', '?', 'NOW()') ->where('t.cat_id = ?', $cat_id) ->addWhere('t.source = ?', $text); $num = $q->execute(); //$num = number of updated rows
Hint: "update" ignores the behaviours. When you want to preserve e.g. the original updated_at date use "update".
Use "->set('ull_location_id', 'NULL')" to create db NULL entries !?!
subselect:
-
SELECT u.id FROM User u WHERE u.id IN (SELECT DISTINCT p.user_id FROM
Post p WHERE p.user_id = u.id AND COUNT(p.id) > 50 GROUP BY p.id)
direct pdo query
-
$dbh = Doctrine_Manager::getInstance()->getCurrentConnection()->getDbh();
$dbh->exec("DROP TABLE my_column");
- @see http://www.ullright.org/ullWiki/show/migrations-in-ullright for more pdo/dbh examples
Clear runtime cache and force reload from database
$models = Doctrine::getLoadedModels(); foreach($models as $model) { $table = Doctrine::getTable($model)->clear(); }