CakePHP: How do I load associated data from inside an entity class? - php

Let's say I have a AuthorsTable with a defined "belongs to many" association with the Articles table defined like so:
// In the initialize function of the AuthorsTable class.
$this->belongsToMany('Articles',
['joinTable' => 'authors_articles']
);
(I don't think that the nature of the join is relevant to the question, but just in the interest of giving full context.)
And now, a I have an $author entity that was passed to my function that does not have the associated data loaded with it (i.e., it was created using something like $author = $authorsTable->get(19);, so it only has the information in the authors table, not from the articles table.
Is there some kind of entity function in which I can load the associated data, i.e., the articles data after the entity has already been created?

chriss's answer suggests using loadInto for this. For CakePHP 3, the PHP you need within any Author Entity method is:
TableRegistry::get($this->source())->loadInto($this, ['Articles']);
The same code from within an AuthorsTable method:
$this->loadInto($author, ['Articles']);

It's a little bit over and I do not know if it's still important to you, but maybe for everyone else.
You can either use the model's loadInto (https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#loading-additional-associations) or you can just use the Lazy Loading Plugin, mentioned in the docs (https://book.cakephp.org/3.0/en/orm/entities.html#lazy-loading-associations)
You can find the plugin here:
https://github.com/jeremyharris/cakephp-lazyload
The plugin works with both methods! If you prefer Eager Loading, you can use contain (normaly faster). Otherwise, the associations will be loaded "on demand" (saving memory).
Personally, I prefer Eager Loading but use the Lazy Loading Plugin if another member of the team (out of ignorance) forgot to load the Associations.

Related

Laravel: What is the purpose of the `loadMissing` function?

The first sentence of the Eager Loading section from the Laravel docs is:
When accessing Eloquent relationships as properties, the relationship
data is "lazy loaded". This means the relationship data is not
actually loaded until you first access the property.
In the last paragraph of this section it is stated:
To load a relationship only when it has not already been loaded, use
the loadMissing method:
public function format(Book $book)
{
$book->loadMissing('author');
return [
'name' => $book->name,
'author' => $book->author->name
];
}
But I don't see the purpose of $book->loadMissing('author'). Is it doing anything here?
What would be the difference if I just remove this line? According to the first sentence, the author in $book->author->name would be lazy-loaded anyway, right?
Very good question; there are subtle differences which are not getting reflected instantly by reading through the documentation.
You are comparing "Lazy Eager Loading" using loadMissing() to "Lazy Loading" using magic properties on the model.
The only difference, as the name suggests, is that:
"Lazy loading" only happens upon the relation usage.
"Eager lazy loading" can happen before the usage.
So, practically, there's no difference unless you want to explicitly load the relation before its usage.
It also worths a note that both load and loadMissing methods give you the opportunity to customize the relation loading logic by passing a closure which is not an option when using magic properties.
$book->loadMissing(['author' => function (Builder $query) {
$query->where('approved', true);
}]);
Which translates to "Load missing approved author if not already loaded" which is not achievable using $book->author unless you define an approvedAuthor relation on the model (which is a better practice, though).
To answer your question directly; yeah, there won't be any difference if you remove:
$book->loadMissing('author');
in that particular example as it's being used right after the loading. However, there might be few use cases where one wants to load the relation before its being used.
So, to overview how relation loading methods work:
Eager loading
Through the usage of with() you can "eager load" relationships at the time you query the parent model:
$book = Book::with('author')->find($id);
Lazy eager loading
To eager load a relationship after the parent model has already been retrieved:
$book->load('author');
Which also might be used in a way to only eager load missing ones:
$book->loadMissing('author');
Contrary to the load() method, loadMissing() method filters through the given relations and lazily "eager" loads them only if not already loaded.
Through accepting closures, both methods support custom relation loading logics.
Lazy loading
Lazy loading which happens through the usage of magic properties, is there for developer's convenience. It loads the relation upon its usage, so that you won't be needing to load it beforehand.
#rzb has mentioned a very good point in his answer as well. Have a look.
I believe the accepted answer is missing one important fact that may mislead some: you cannot run loadMissing($relation) on a collection.
This is important because most use cases of lazy eager loading relationships are when you already have a collection and you don't want to commit the n+1 sin - i.e. unnecessarily hit the DB multiple times in a loop.
So while you can use load($relation) on a collection, if you only want to do it if the relationships haven't already been loaded before, you're out of luck.
its mean do not repeat the query
to be clear about it
if you use : load() 2 times the query will repeat even if the relationships exists
while : loadMissing() is check if the relationship has loaded . it will not repeat the query . beacuse it has already loaded before by [ load() or with() ] = egear load
DB::enableQueryLog();
$user = User::find(1);
// see the query
$user->load('posts');
$user->load('posts');
$user->loadMissing('posts'); // put it on top to see the difference
dd(DB::getQueryLog());
that's what i think its purpose
Very useful for APIs
The use of with, loadMissing or load can has more importance when use it in API environment, where the results are passed to json. On this case, lazy loading hasn't any effect.
Lets say you have multiple relationships.
book belongs to an author and book belongs to a publisher.
so first you might load it with one relationship.
$books->load('author');
and later on certain condition you want to load another relationship into it.
$book->loadMissing('publisher');
But I don't see the purpose of $book->loadMissing('author');. Is it
doing anything here? What would be the difference if I just remove
this line? According to the first sentence, the author in
$book->author->name would be lazy-loaded anyway, right?
Suppose say
public function format(Book $book)
{
//book will not have the author relationship yet
return [
'name' => $book->name, //book will not have the author relationship loaded yet
'author' => $book->author->name //book will now have the author relationship
];
}
Difference between above and below code is when will the relationship be loaded and how much control you have over the property.
public function format(Book $book)
{
$book->loadMissing('author'); // book will now have the author relationship
return [
'name' => $book->name, // book have the author relationship loaded
'author' => $book->author->name // book have the author relationship loaded
];
}
Both answers here have covered pretty well what the technical difference is, so I'd refer you to them first. But the "why" isn't very evident.
Something I find myself preaching a lot lately is that Eloquent is really good at giving you enough rope to hang yourself with. By abstracting the developer so far away from the actual SQL queries being produced, especially with dynamic properties, it's easy to forget when your database hits are hurting your performance more than they need to.
Here's the thing. One query using an IN() statement on 1000 values takes about the same execution time as one query running on one value. SQL is really good at what it does- the performance hit usually comes with opening and closing the DB connection. It's a bit like going grocery shopping by way of making one trip to the market for each item, as opposed to getting it all done at once. Eager-loads use the IN statements.
Lazy-loading is good for instances where you're handling too much data for your server's RAM to cope with, and in my opinion, not good for much else. It handles only one entry at any given moment. But it's reconnecting each time. I can't tell you the number of times I've seen Transformer classes, which should be responsible only for reformatting data as opposed to retrieving it, leveraging those dynamic properties and not realizing that the data wasn't already there. I've seen improvements as dramatic reducing execution time from 30 minutes to 30 seconds just by adding a single line of eager-loading prior to the Transformer being called.
(By the way, batching might be considered the happy-medium, and Eloquent's chunk() method offers that too.)
To answer your question a little more directly; if you're dealing with an instance where it's a one-to-one relationship, and it's going to be used in only one place, then functionally there is no difference between load, loadMissing, or a lazy-loading dynamic property. But if you have a many-to-many, it may be worthwhile to gather up all that data all at once. One book can have many co-authors. One author can write many books. And if you're about to loop through large sets of either, go ahead and make the most of your trip to the market before you start cooking.

How does the Doctrine Repository mechanism of lazy loading entities work?

So, I want to understand how the Doctrine Repository mechanism works.
For my entities I use annotations, so the resulting object is built somewhere during the execution of the script.
I'd like to unserstand which are the possibile ways of implementing the lazy loading of entities from another entity.
In concrete, using Doctrine, I have the ability to fetch information of related object (from the Symfony book). This fetching is done in a lazy way: only if I call the method to get the information about the Entity it is loaded from the database querying it.
Now, I'd like to better understand this mechanism: how an entity can implement repository methods?
How can I reproduce this mechanism to implement it in other context similar to the one of a database data retrieval?
As the resulting object is really big, is there someone who can put me on the right way?
Which classes should have I read to understand the mechanism?
Are there any articles/posts that better explain how this mechanism is implemented?
Are there better (or simply simpler) ways of implementing it?
I think the best description of the lazy loading can be found in Doctrine developer articles.
http://www.giorgiosironi.com/2009/07/lazy-loading-of-objects-from-database.html
http://www.giorgiosironi.com/2009/08/doctrine-2-now-has-lazy-loading.html
The main idea is to insert into Product's category list a set of objectes that are subclasses of Category. These and called "proxy objects" and created "on the fly" when Product is retrieved from database. These proxy objects have the same interface as Category object, but add functionality of loading actual Category items from database when needed.
Doctrine actually creates a extra object (think proxy) that keeps a record of what properties have actually been accessed.
See this part from the documentation :
32.4.2. Association proxies
The second most important situation where Doctrine uses proxy objects is when querying for objects. Whenever you query for an object that has a single-valued association to another object that is configured LAZY, without joining that association in the same query, Doctrine puts proxy objects in place where normally the associated object would be. Just like other proxies it will transparently initialize itself on first access.
doctrine documentation
You can create a custom repository for an entity: http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes
Once you have your own custom repository class you can create queries that fetch all of the information you need in one query rather than relying on lazy loading.
So say you have an Product entity which has one or more Category entities using a ManyToMany relationship you could create a function in your custom repository to fetch all products with their categories in one query:
public function fetchProductsWithCategories()
{
return $this->getEntityManager()
->createQuery(
'SELECT p, c FROM Product p join p.categories c'
)
->getResult();
}
Then in your controller you would have something like:
$repo = $this->getDoctrine()->getManager()->getRepository('Product');
$products = $repo->fetchProductsWithCategories();
Edit: missed c in select

PHP Objects - Patterns and correct usage

I'm just wondering if someone can help me understand how to make the best use of objects in PHP.
My understanding of a PHP object is that is should represent an entity, providing methods to get and alter the properties of that entity. For example an object entitled Post would hold all the properties of a single post, which could be accessed and modified as appropriate.
What causes me some confusion is that libraries like CodeIgniter don't use objects in this manor. They treat classes more like wrappers for a group of functions. So a 'Posts' class in CodeIgniter would not hold properties of one post, it would provide functions for fetching, editing and deleting posts.
So what happens if I want to get every post out of a database and put it into a Post object? My understanding of it is I would in fact need two classes 'Posts' and 'Post', one that defines the Post object and one that handles fetching the Posts from the database and putting them into Post objects.
Do these two types of class have a name ('Proper' objects / Collections of functions)? And is it common to have two classes working together like this or have I completely misunderstood how to use objects?
Instead of having a Post object would it make more sense to have a method in my Posts class called getSinglePost($id) that just returned an array?
Hopefully that question makes sense, looking forwards to getting some feedback.
For an introduction, see What is a class in PHP?
For the answer, I'll just address your questions in particular. Search for the terms in bold to learn more about their meaning.
My understanding of a PHP object is that is should represent an entity, providing methods to get and alter the properties of that entity.
Entities are just one possible use for objects. But there is also Value Objects, Service Objects, Data Access Objects, etc. - when you go the OO route, everything will be an object with a certain responsibility.
What causes me some confusion is that libraries like CodeIgniter don't use objects in this manor.
Yes, Code Igniter is not really embracing OOP. They are using much more of a class-based-programming approach, which is more like programming procedural with classes and few sprinkles of OOP.
They treat classes more like wrappers for a group of functions. So a 'Posts' class in CodeIgniter would not hold properties of one post, it would provide functions for fetching, editing and deleting posts.
That is fine though. A posts class could be Repository, e.g. an in-memory collection of Post Entities that has the added responsibility to retrieve and persist those in the background. I'd be cautious with Design Patterns and Code Igniter though since they are known to use their own interpretation of patterns (for instance their Active Record is more like a Query Object).
So what happens if I want to get every post out of a database and put it into a Post object?
Lots of options here. A common approach would be to use a Data Mapper, but you could also use PDO and fetch the data rows directly into Post objects, etc.
My understanding of it is I would in fact need two classes 'Posts' and 'Post', one that defines the Post object and one that handles fetching the Posts from the database and putting them into Post objects.
That would be the aforementioned Repository or Data Mapper approach. You usually combine these with a Table Data Gateway. However, an alternative could also be to not have a Posts class and use an Active Record pattern, which represents a row in the database as an object with business and persistence logic attached to it.
Do these two types of class have a name ('Proper' objects / Collections of functions)? And is it common to have two classes working together like this or have I completely misunderstood how to use objects?
Yes, they work together. OOP is all about objects collaborating.
Instead of having a Post object would it make more sense to have a method in my Posts class called getSinglePost($id) that just returned an array?
That would be a Table Data Gateway returning Record Sets. It's fine when you don't have lots of business logic and can spare the Domain Model, like in CRUD applications
Class should ideally has the same interpretation as anywhere else in PHP as well. Class starts with abstraction, refining away what you don't need. So it's entirely up to you to define the class the way you want it.
Codeigniter does have a strange way of initiating and accessing objects. Mainly because they are loaded once and used afterwards, prevents it from having functionality around data. There are ways around it and normal handling of classes still possible. I usually use a auto loader and use normal classes.
"So what happens if I want to get every post out of a database and put it into a Post object? My understanding of it is I would in fact need two classes 'Posts' and 'Post',"
You are essentially referring to a MODEL to access the data ("posts") and an Entity to represent the "post". So you would load the model once and use it to load up as many entities as you would like.
$this->load->model("posts");
$this->posts->get_all(); // <- This can then initiate set of objects of type "Post" and return. Or even standard classes straight out from DB.
Your understanding of an object is correct. A post is a single object of a class Post. But of course you need a function, that retrieves posts from a database or collects them from somewhere else. Therefore you have so called Factory classes. That's what can cause some confusion.
Factories can be singletons, which normally means that you have one instance of this class. But you don't need to instantiate a factory at all (and instead use static functions to access the functionality):
$posts = PostFactory::getPosts();
And then the function:
static function getPosts() {
$list = array();
$sql = "select ID from posts order by datetime desc"; // example, ID is the primary key
// run your sql query and iterate over the retrieved IDs as $id
{
...
$post = new Post($id);
array_push($list, $post);
}
return $list;
}
Inside this factory you have a collection of "access"-functions, which do not fit elsewhere, like object creation (databasewise) and object retrieval. For the second part (retrieval) it is only necessary to put the function into a factory, if there is no "parent" object (in terms of a relation). So you could have an entity of class Blog, you instantiate the blog and then retrieve the posts of the blog via the blog instance and don't need a separate factory.
The naming is only there to help you understand. I wouldn't recommend to call a class Post and it's factory Posts since they can easily be mixed up and the code is harder to read (you need to pay attention to details). I usually have the word "factory" mixed in the class name, so I know that it is actually a factory class and others see it too.
Furthermore you can also have Helper classes, which don't really relate to any specific entity class. So you could have a PostHelper singleton, which could hold functionality, which doesn't fit neither in the object class nor in the factory. Although I can't think of any useful function for a Post object. An example would be some software, which calculates stuff and you have a Helper, which performs the actual calculation using different types of objects.

Should I use App::import('Model', ...) or ClassRegistry(...)?

Because of other answers (like this), I'm just wanting to clarify what should be used in CakePHP 1.3.
Specifically, I have a situation that calls for a Model to depend on another, so from a method in that Model I'd like to load another, do some stuff with the info, etc.
The documentation for the App Class says:
In previous versions there were different functions for loading a needed class based on the type of class you wanted to load. These functions have been deprecated, all class and library loading should be done through App::import() now.
I'm assuming this covers the use of ClassRegistry, etc, but I just want to it to be clear, and certain:
Should I use App::import('Model', ...) to utilize one Model from another, or something else? If something else, what?
It appears that, even two years since 2008, the best method is to use ClassRegistry::init(), despite the cited documentation.
This is made evident in the actual API/documentation for the specific classes/methods.
App::import()
Finds classes based on $name or specific file(s) to search. Calling App::import() will not construct any classes contained in the files. It will only find and require() the file.
ClassRegistry::init()
Loads a class, registers the object in the registry and returns instance of the object.
Examples Simple Use: Get a Post model instance ClassRegistry::init('Post');
As you can see, even the API Documentation points out examples of using ClassRegistry to load models, instantiating them for you, as opposed to App::import (which does much less), and despite the changed wording in the CakePHP "Book" documentation.
If you can relate the models then the best way is to Dynamically bind the relations using
$this->bindModel("hasOne" => array("Model2")).
If you can't relate the model and you want to use the second model in just one occurrence then you can use
ClassRegistry::init('Model2')->find('allThatIWant');
if you want to use it in several occurrence then you must try
$this->model2 = & ClassRegistry::init('Model2')
$this->model2->find('allThatIWant');
As of 2.6.x of course it is ClassRegistry::init() still.
There is a major difference. App::import will just include/require it. On the other hand ClassRegistry::init() will instantiate it and fetch you a fully loaded object of the model.
So to say, for example you loaded a model in beforeFilter of your AppController. You add some custom properties to it using $this->Model->__something. Now you do call ClassRegistry::init('Model') somewhere where you do not have $controller object available, for example, in a behavior. The object returned by ClassRegistry::init('Model') will have your custom property $this->Model->__something in tact.
Btw, $controller->loadModel() seems the ideal way to load model where you have a $controller object available, for example in your components.
$this->loadModel('model name') will do unless u need it for the entire controller, Then just define the relationship in the model such as hasone, belongsto... and call $this->model->model2.

How much should doctrine record do?

I'm creating my own CMS and use doctrine for database.
Now I wonder, when I crate Post record, how much work should that record do?
An example:
I have Post -> Categories relation (one to many), should I create separate functions to append categories (to look if Post already has category, etc. ) or should Post do that using accessors / mutators?
What's the best practice?
I think adding methods for the purprose you described is a good idea. Doctrine can sometimes be a bit tricky if you try to override the default actions that happen when accessing the properties.
In general, if there's anything that needs more than the default action, I would recommend having it as a method in the model class.
If you have a specific table with some table-specific actions, such as get every object by some rule, then it's a good idea to add a new method to the table-specific SomeTable class.
Since this is kind of like ActiveRecord, you would have the domain logic in the Doctrine record object.

Categories