Does Zend TableGateway automatically cache duplicated queries? - php

I remember reading something similar about Symfony's Doctrine, but I can't find anything about this in Zend 2 documentation.
Here is the question explained:
Let's say that in a single controller action I call two model functions (both in same model): both functions run exactly the same TableGateway query sets. These queries only SELECT data. Furthermore there are no INSERT/UPDATE operations anywhere in this action.
In this case, would Zend run the query sets twice? Or, seeing that they are duplicated and no INSERT/UPDATE operation is done in-between, it would run the query set just once, and the second time return it from some internal cache.
ps. Just in case, please understand that I don't need general best practice advice, just the specific answer from someone who knows the depths of Zend's core.

No. It would be bad to do that anyway as your application has no idea if another application has written to the database and invalidated your cached query.
If you have query cache enabled in my sql then the query could be cached as the rdbms knows if that data can be cached or if it's been changed.

Related

Force doctrine to always refresh

I've got a script that fetches data from a database using doctrine. Sometimes it needs to fetch the data for the same entity, the second time however it uses the identity map and therefor might go out of sync with the database (another process can modify the entities in the db). One solution that we tried was to set the query hint Query::HINT_REFRESH before we run the DQL query. We however would like to use it also with simple findBy(..) calls but that doesn't seem to work? We would also like to be able to set it globally per process so that all the doctrine SELECT queries that are run in that context would actually fetch the entities from the DB. We tried to set the $em->getConfiguration()->setDefaultQueryHint(Query::HINT_REFRESH, true); but again that doesn't seem to work?
Doctrine explicitly warns you that it is not meant to be used without a cache.
However if want to ignore this, then Cerad's comment (also mentioned in in this answer) sound right. If you want to do it on every query though you might look into hooking into a doctrine event, unfortunately there is no event for preLoad, only postLoad, but if you really don't care about performance you could create a postLoad listener which first gets the class and id of the loaded entity, calls clear on the entity manager and finally reloads it. Sounds very wrong to me though, I wash my hands of it :-)

Laravel Eloquent: How does it work? Based on dynamic Schema MetaData-Lookup = Performance?

The whole persistance layer is a rather big and complex laravel component. Is there someone who has already looked at it in depth and can explain it in a few words, whats going on schematically under the hood?
Eloquent (in contrast to other ORM Layers) seems to not cache/store the Column Metadata somewhere in the application? Or does it? (In Java JPA or Doctrine this is done via Annotations, but laravel seems to not have this metadata?)
This would mean that it has to query on every request the INFORMATION_SCHEMA.COLUMNS from MySQL. Does this mean, that laravel will for every simple SQL query have to iusse two queries (the first one to get the column/table definitions?)
Will calling hasColumn on a new Instance/Facade inevitably lead to an SQL Query, just to retrieve the metadata/table-definition?
As far as i know, you are right, Eloquent does not cache or store the column metadata. But this does not mean that each query requires a second on which requests the information schema. The query builder just assumes that you know which column names are legal and creates and sends the query. This means, that if you select an unknown column, you'll get an exception! Finally hasColumn leads to an SQL query.

Set Laravel Eloquent model's to eager load by default

Laravel's eloquent models are set to lazy load by default. The problem is that it makes a lot of query to the database and especially during high traffic, the laravel application crashes whereas a similar application build on Yii 1 has no issues.
After installing the Laravel's debug bar, the problem is too many queries being made on every page load. The next step is to query optimization. I have been using eager loading as directed in the Laravel's documentation but still too many queries.
I was wondering if there is a way to set Eloquent to only "Eager Load" in dev environment. That way when the page fails to load, identifying issue would be easier.
You could set defaults relations to "eager load" directly on the models :
Class MyModel extends Model {
protected $with = ['relation'];
}
The solution for high database load is Cache.
Caching properly could give you incredible performance during high traffic, because it reduces common database queries to zero, and redirect them to RAM ones, which are faster.
Enabling Route Caching will increase perfomance too:
php artisan route:cache
EDIT:
As Fx32 points, you should make sure that you need Eloquent and wouldn't be better to make the same query directly to the DB, joining the tables you need and making a single query instead of a lot:
Cache is not a good solution as a fix for bad database querying.
Eloquent is great, but often it's better to write proper queries with
some joins. Don't just bash away at your DB and then throw all the
results in a cache, as it will introduce new problems. If your use
case is not a flat CRUD API, ActiveRecord patterns might not be the
best solution anyway. If you carefully select and join results from
the DB, and want to speed up retrieval of such items, caching can
help.

Can a Controller have database queries (MySQL)? If yes, when?

I am reading lots of tutorials on MVC, so my question, can a perfect PHP MVC framework have database queries in Controller? As I understand, the most comfortable way is to put all database queries in Model, right? And if I have POST or smth, I just pass that POST to Model and it makes all inserts and etc. ?
Or I am missing something? And if Controller can have a database queries, in which situation would it be?
No controller may not have any db related code - any DB queries may be stored in model in MVC architecture - controller only works with models, but not directly with DB
EDIT: Most frameworks will allow calling SQL directly from Controller - but then it is not MVC, but bunch of objects
No Controller must not IDEALLY and CONCEPTUALLY contain any database queries. If you have some queries in the controller itself then it will take away some key advantages of the MVC architecture such as Code Segregation and so on.
Ideally your,
Model Classes (M) must contain DB queries and any interactions with DB via DB objects. A model ideally represents a Table in the DB or a file used for io
Views (V) must contain HTML with very little PHP. In most conditions only loops and conditional statements are used
Controller Classes (C) must contain all the business logic of you application, error handlers and so on.
It is very useful to maintain the MVC Architecture in regards to Maintain, Debug and also code understanding form a new developers prospective. The norms bring in a lot of benefits as mentioned above.
Technically - yes, it is possible. But it would break the whole idea behind MVC.
In my software, I'm making it possible to extract query objects from model and execute them from inside controllers:
$model->dsql()->where('age>',20)->do_delete();
So technically - yes, controller can execute queries, but it must rely on the model to build that query.

How to handle database access in Zend Framework?

To begin: i'm not an expert in Zend Framework and doing something terrible wrong. I'm sure of that. I think there's something wrong with my design patterns.
As an example:
I'm building access management with Zend_ACL (Access Control List)
There are three tables in the database:
roles
resources
permissions
the permissions table handles the role-resources relation.
I made a model for each table, it extends Zend_Db_Table_Abstract. So far so good.
Now in the ACL I load the resources, role and permissions on a page request and add it to the ACL.
Now the part I'm doing something wrong: The way I do it is call methods from the tablemodels that give me the required data. But when I look at my profiler it takes 117 select queries and takes 0.7 seconds just to load the ACL. No queries for the underlying system yet. This can't be good and I'm sure there is a better way. I just can't find anything about this on google or anywhere.
Is there someone who can tell me if I'm doing something wrong and if I am, what I should to to speed it up? Should I load everything in one query to models and let them handle it? How do I do that, are there any examples?
Thanks in advance!
It's not clear exactly what you're doing, but you shouldn't be grabbing generating so many queries.
Some things to think about:
Do you need to load the full ACL on every request? Perhaps you could structure your data-access layer in such a way that it checks for relevant permissions when a user attempts to perform some action.
If you do need the full ACL, you ought to be able to construct a single query to grab all the relevant data. Perhaps eschewing the Zend_Table stuff here and just executing a raw custom query? Not exactly a best-practice, but if you're loading everything, it's just one query.
More concrete code in your question would definitely produce more concrete answers.
If you do need to load all the stuff, why not load it just once and serialize your acl object and keep it in session or cache ?
Every time you need to access your ACL object, check if the cache or the session variable is set or not. If it is set, you can just avoid running the queries and just unserialize the object from session or cache.
I agree this is a dirty solution, but it works and will not run the 117 queries each time.

Categories