Eager Loading on 3 Models in Laravel 5 - eloquent

I have 3 Models that are related so :
"Tutorial" belongs To "Title" that belongs to "Course". Or (the other way) . A "Course" has many "Titles" that have many "Tutorials" .
And I want to find a course based on its id and grab all its titles and tutorials using the eager loading .
the code looks so :
$course = Course::with('titles')->where('id','=',$id)->get();
// this returns only a Course with its titles , but I want to get also tutorials that belongs to each title.

You can eager load nested relations with the dot-syntax as documented here
$course = Course::with('titles.tutorials')->find($id);
As you can see I also changed the where('id', '=', $id) to find($id). This will do the same but also only return one result instead of a collection.

Related

Yii2: Am I able to use multiple models in a search model?

In Yii2, am I able to include two models (active records) in one search model and display them in a gridview?
For example, I have two tables, "customers", and "customer_contacts".
In my search model I am using Customers as my main model, while I wish to "left join" to CustomerContacts, and eventually display the Customers.name and CustomerContacts.phoneNumber in the gridview (in dataProvider).
Can someone please guide me on this.
Thank.
Option 1:
In the customer model add this function:
Public function getCustomerContact(){
Return $this-> hasOne( CustomerContact::className,[customer_id,id]);
}
Then in your grid view you can easily reference the contact as follows:
customerContact.name
Note that this will only work if there is a one to one relationship between the tables
Option 2: (faster but more challenges)
In the data provider, use a query rather than a model ie $query = new \yii\db\Query();
You can then do all joins etc in the data provider. It is much faster but it requires a little more know-how
you can do this by applying left-join in searchModel as following
$query = Customers::find();
$query->joinWith('customer-contact');
And also make hasOne relation with CustomerContact in Customer.php

CRUD orderBy with relationship

I'm having difficulty ordering the CRUD rows by a related value. In my main case I want to order jobs by the weight of their associated status
Job (table)->status_id ---> Status (table)->weight
I've got belongsTo and hasMany relationships setup correctly and add / edit etc, works well, I just can't figure out how to set the $this->crud->orderBy()
It's no different than sorting any Laravel model by its relation. And I think the standard way is to use Laravel's eager loading for that:
$this->crud->query = $this->crud->query->with(['status' => function ($query) {
$query->orderBy('weight', 'desc');
}])->get();
Hope it helps!

How make a form for many to many relations with additional columns in symfony2?

I have Classes like below :
Class Order
{
// Order have many Product
// One to Many -> ProductOrder
}
Class ProductOrder
{
$order
$product
$type
// other variable
}
Class Product
{
// Product has many Order
// One to Many -> ProductOrder
}
Basically I have #manytomany with additional columns, so I need to have ProductOrder in middle based on the note in yellow box here.
My question is how I can have one form with One Order and Multiple Products.
Something like How to setup a many to many form in Symfony2 but I need the middle UserTask class. If I use Many-to-many with no middle class I can create form easily and everything works fine, but having the middle class and the same functionality is what I need.
You need to use form collections.
My question & answer regarding form collections:
Form Collection Error
Form Collections from Symfony 2 docs:
http://symfony.com/doc/current/cookbook/form/form_collections.html
Symfony 2.0: Embedded Forms for Collections:
http://www.scott-sherwood.com/?p=90

difference between 2 code segments

What is the difference between
ObjectQuery<SalesOrderHeader> query =
context.Contacts.Include("SalesOrderHeaders").Include("SalesOrderDetails");
and
Contact contact =
context.Contacts.Include("SalesOrderHeaders.SalesOrderDetails").FirstOrDefault();
Any advantage of using one over the other?
My main confusion is for the using 2 Include in first one and using 2 tables in second Include.
Thanks in advance.
On entity framework you have something called navigation properties (Named on your .edmx model) so you can access related entities based on them, in other words, you can use your navigation properties to eager load (include) related data..
I'm guessing you have this relationship: One Contact can have many SalesOrderHeaders and one SalesOrderHeader can have many SalesOrderDetails, so if you start loading from contacts entity and want to have both relations loaded you should do:
Contact contact = context.Contacts.Include("SalesOrderHeaders").Include("SalesOrderHeaders.SalesOrderDetails").FirstOrDefault();
as you can see, we're using first include to bring SalesOrderHeaders from DB and the secound one to bring SalesOrderDetails through SalesOrderHeaders navigation property as we're starting from Contacts

DDD and Entity Framework - manually building associations

If we manually build our associations will we have to expose foreign keys in our domain model?
For example, if I a retrieve all Products and all Categories, the only way I can manually build the Product.Categories property is if I expose the ProductCategory mapping in my model?
I'd rather not do this if there is an alternative (note that eager loading via EF is not an option as I have two many associations to load).
You could add a partial class "Product" to your project and extend your "Product" entity with an IEnumerable<Category> property "Categories" (Or even a method that returns IEnumerable<Category>).
This way you could implement the retrieval of "Categories" yourself.
The solution was to use a Linq projection to retrieve the relevant keys.
var tags = (from p in postRepo.GetAll()
from t in p.Tags
select new
{
PostId = p.Id,
Tag = t
}).Take(1000).ToList();
I stick the results of the above query into a List<KeyValuePair<Guid, Tag>> which is then cached. When I load a Post I can manually build it's "Tags" collection from the cache.
This is an approach that we have had to take with a number of associations now. Whilst lazy loading is very convenient, IMHO it should not be used with your Views.
By caching common associations using the above method, we were able to reduce a page previously issuing 59 queries (as a result of lazy loading) to just 6 queries.