nHibernate has a great feature called filters, so i can create criterias globally for my applications. I'm starting a project in PHP and i need to use an ORM, i'd like to know if Doctrine has a similar feature to manage query conditions.
thanks
I think what you are looking for are Doctrine Query Hooks.
There a numerous hooks for preUpdate, preSave, preCreate, postCreate, postUpdate, postSave, preSelect, and so on and so forth.
Hope this helps.
Doctrine 2.2 features a filter system that allows the developer to add SQL to the conditional clauses of queries, regardless the place where the SQL is generated (e.g. from a DQL query, or by loading associated entities).
The filter functionality works on SQL level. Whether a SQL query is generated in a Persister, during lazy loading, in extra lazy collections or from DQL. Each time the system iterates over all the enabled filters, adding a new SQL part as a filter returns.
By adding SQL to the conditional clauses of queries, the filter system filters out rows belonging to the entities at the level of the SQL result set. This means that the filtered entities are never hydrated (which can be expensive).
Related
The tutorial of zend framework show that I can use Zend\Db\ResultSet\HydratingResultSet to return a model object using the dbAdapter ,select query and a model prototype. But in most case writing the website code I use multi-table query and the hydrator can not fix this problem but just a single table query. How should I deal with this kind of problem.
hydrator doc
And this problem can also happen when encounting the pagination which also only take one prototype.
paginator doc
Depending on the query, you might need a custom ResultSet that knows how to deal with the multi-row potential of a multi table query, and mapping that dataset appropriately.
Additionally, if you find yourself getting into very advanced object relationships with Zend\Db, that might be the time to start considering Doctrine2 (or a similar ORM).
I'm developing a ws with Symfony2 / Doctrine2, and I'm trying to hook into Doctrine2 lifecycle and trigger a function before any SELECT action - but without any luck. Basically, i'd like to dynamically manipulate the selection queries adding limit/offset when certain parameters are found in the request, but it seems that Doctrine2 hooks concern only insert, delete and update actions. Am i missing something?
Thanks.
U have to use Doctrine Filter
Doctrine 2.2 features a filter system that allows the developer to add SQL to the conditional clauses of queries, regardless the place where the SQL is generated (e.g. from a DQL query, or by loading associated entities).
A way to deal with this would be to register a custom event that is dispatched before a select. You have already referenced the source that shows examples of how to do it.
Symfony ACL allows me to grant access to an entity, and then check it:
if (false === $securityContext->isGranted('EDIT', $comment)) {
throw new AccessDeniedException();
}
However, if I have thousands of entities in the database and the user has access only to 10 of them, I don't want to load all the entities in memory and hydrate them.
How can I do a simple "SELECT * FROM X" while filtering only on the entities the user has access (at SQL level)?
Well there it is: it's not possible.
In the last year I've been working on an alternative ACL system that would allow to filter directly in database queries.
My company recently agreed to open source it, so here it is: http://myclabs.github.io/ACL/
As pointed out by #gregor in the previous discussion,
In your first query, get a list (with a custom query) of all the object_identity_ids (for a specific entity/class X) a user has access to.
Then, when querying a list of objects for entity/class X, add "IN (object_identity_ids)" to your query.
Matthieu, I wasn't satisfied by replying with more of conjectures (since my conjectures don't add anything valuable to the conversation). So I did some bench-marking on this approach (Digital Ocean 5$/mo VPS).
As expected, table size doesn't matter when using the IN array approach. But a big array size indeed makes things get out of control.
So, Join approach vs IN array approach?
JOIN is indeed better when the array size is huge. BUT, this is assuming that we shouldn't consider the table size. Turns out, in practice IN array is faster - except when there's a large table of objects and the acl entries cover almost every object (see the linked question).
I've expanded on my reasoning on a separate question. Please see When using Symfony's ACL, is it better to use a JOIN query or an IN array query?
You could have a look into the Doctrine filters. That way you could extend all queries. I have not done this yet and there are some limitations documented. But maybe it helps you. You'll find a description of the ACL database tables here.
UPDATE
Each filter will return a string and all those strings will be added to the SQL queries like so:
SELECT ... FROM ... WHERE ... AND (<result of filter 1> AND <result of filter 2> ...)
Also the table alias is passed to the filter method. So I think you can add Subqueries here to filter your entities.
Can someone provide me a couple clear (fact supported) reasons to use/learn DQL vs. SQL when needing a custom query while working with Doctrine Classes?
I find that if I cannot use an ORM's built-in relational functionality to achieve something I usually write a custom method in the extended Doctrine or DoctrineTable class. In this method write the needed it in straight SQL (using PDO with proper prepared statements/injection protection, etc...). DQL seems like additional language to learn/debug/maintain that doesn't appear provide enough compelling reasons to use under most common situations. DQL does not seem to be much less complex than SQL for that to warrant use--in fact I doubt you could effectively use DQL without already having solid SQL understanding. Most core SQL syntax ports fairly well across the most common DB's you'll use with PHP.
What am I missing/overlooking? I'm sure there is a reason, but I'd like to hear from people who have intentionally used it significantly and what the gain was over trying to work with plain-ole SQL.
I'm not looking for an argument supporting ORMs, just DQL when needing to do something outside the core 'get-by-relationship' type needs, in a traditional LAMP setup (using mysql, postgres, etc...)
To be honest, I learned SQL using Doctrine1.2 :) I wasn't even aware of foreign-keys, cascade operations, complex functions like group_concat and many, many other things. Indexed search is also very nice and handy thing that simply works out-of-the-box.
DQL is much simpler to write and understand the code. For example, this query:
$query = ..... // some query for Categories
->leftJoin("c.Products p")
It will do left join between Categories and Products and you don't have to write ON p.category_id=c.id.
And if in future you change relation from one-2-many to let's say many-2-many, this same query will work without any changes at all. Doctrine will take care for that. If you would do that using SQL, than all the queries would have to be changed to include that intermediary many-2-many table.
I find DQL more readable and handy. If you configure it correctly, it will be easier to join objects and queries will be easier to write.
Your code will be easy to migrate to any RDBMS.
And most important, DQL is object query language for your object model, not for your relational schema.
Using DQL helps you to deal with Objects.
in case inserting into databae , you will insert an Object
$test = new Test();
$test->attr = 'test';
$test->save();
in case of selecting from databae, you will select an array and then you can fill it in your Object
public function getTestParam($testParam)
{
$q=Doctrine_Query::create()
->select('t.test_id , t.attr')
->from('Test t ')
$p = $q->execute();
return $p;
}
you can check the Doctrine Documentation for more details
Zeljko's answer is pretty spot-on.
Most important reason to go with DQL instead of raw SQL (in my book): Doctrine separates entity from the way it is persisted in database, which means that entities should not have to change as underlying storage changes. That, in turn, means that if you ever wish to make changes on the underlying storage (i.e. renaming columns, altering relationships), you don't have to touch your DQL, because in DQL you use entity properties instead (which only happen to be translated behind the scenes to correct SQL, depending on your current mappings).
How to speed up Doctrine in routine statements like getting collection or related data from object?
What's better if i want to get list with related tables data. Native sql in doctrine or using doctrine_query?
Several things could help. I've noticed substantially better performance with Doctrine 2.
Working with Doctrine 1.2 one of the best things you can do is hydrate to as simple of a structure as you can. I had reports that I could definitely not hydrate to record on but worked find if I hydrated to scalar or array.
Other than that, make sure you use DQL instead of the magic finders to load objects. Using DQL will help ensure you load all parts of your object graph that you need in one query (see lazy loading).
Hope some of this helps.