How to chain with clauses in Laravel - mysql

I've a User model which have many Orders (Order model), and each Order belongs to a Translator (Translator Model).
The behavior that I'm trying to reach is when I fetch a User by his Id, I want to get his orders and the translator associated with each order.
I try to use this code: $user = User::where('id', $id->id)->with('orders')->with('translator')->get();, I expect that it will return the proper data which should be something like this:
{
...user data,
orders: [
{
...order_data,
translator: {
...translator_data
}
}
]
}
but that doesn't work.
Is there anyway to get this behavior in Laravel ?

You can eager load nested relationships using the . to distinguish this:
$user = User::where('id', $id->id)->with('orders.translator')->first();
// or
$user = User::with('orders.translator')->find($id->id);
Side Note, if $id is a User instance you can Lazy Eager Load the relationship on it:
$id->load('orders.translator');
Laravel 7.x Docs - Eloquent - Relationships - Eager Loading - Nested Eager Loading with
Laravel 7.x Docs - Eloquent - Relationships - Eager Loading - Lazy Eager Loading load

Related

Doctrine GROUP BY in a custom method - Symfony Repository

I would like to group my query with Doctrine in Symfony3 in one of my repository but will not return any result. Mainly I think because of the attached relations to the entity.
the method looks as it follows
public function findAllByCurrentDemands($ids) {
$query = $this->createQueryBuilder('pt')
->select('pt')
->where('pt.id IN (:ids)')
//->groupBy('pt.demand_id')
->setParameter('ids', $ids)
->getQuery()->getResult();
dump($query);
die;
}
the raw sql example which is working in console and should be transformed to doctrine
SELECT demand_id
FROM ProductType
WHERE id IN (313,315,317,320,321,765,761,763,766)
GROUP BY demand_id;
How can I do this in a doctrine query like holding the attached relations?

Disable Doctrine automatic queries

With Symfony 4.2 and Doctrine, I want to disable automatic queries.
If I execute this simple example :
$posts = $em->getRepository(Post::class)->findAll();
foreach ($posts as $post) {
dump($post->getCategory()->getName();
}
Doctrine will search categories by itself. But I want to disable that. to force me to join (LEFT or INNER in repository).
It's possible ? Thanks
Implicit data fetching from database by accessing linked entity properties is one of core principles of Doctrine and can't be disabled. If you want to just fetch some data explicitly - you need to construct your own partial query and hydrate data either as array or simple object so your fetched results will not became entities.
Nothing can automatically disable this behavior and force you to write JOIN clauses, except your wishes.
This behavior (which is called lazy loading) is one of the main common behavior of all ORMs.
If you are not happy with this (and you probably have good reasons), then consider writing your own DQL queries, which are limited to your selected fields. What is not in your query will not be fetched automatically afterwards.
Write this method in your custom PostRepository class :
public function findAll(){
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('p')
->from('Post', 'p');
return $qb->getQuery()->getResult();
}
Then in your controller, you can do the same as before:
$posts = $em->getRepository(Post::class)->findAll();
foreach ($posts as $post) {
dump($post->getCategory()->getName();
}
Calling the getName() method from the Category entity will now throws an error, and will not launch any hidden SQL queries behind. If you want to play with Posts and Categories together, then you can adapt your findAll() method like this :
public function findAll(){
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('p, c')
->from('Post', 'p');
->join('p.category', 'c')
return $qb->getQuery()->getResult();
}

Eloquent query problem using with() function for model relationship eager loading

How do write this eloquent query in Laravel so that it eager loads with() the relationship model in this example between a User model and Profile model? I was trying to avoid 2 separate queries.
I feel I am close, but somethings not quite right.
$author = User::where('id', $id)->with('profile')->get();
The collection is returning the user details correctly. But it's showing the profile relationship as null.
#relations: array:1 [▼
"profile" => null
]
I believe I have things setup correctly with a User model and a Profile needed relationships.
User.php
public function profile()
{
return $this->hasOne('App\AuthorProfile', 'user_id');
}
AuthorProfile.php
public function user()
{
return $this->belongsTo('App\User');
}
Assuming for AuthorProfile model table you have record with id of user it should be fine.
However you wrote:
I was trying to avoid 2 separate queries.
Well, it's not true, if you have single record, eager loading won't help you at all. In this case 2 queries will be execute - no matter if you use eager loading or you won't.
Eager loading would help if you had multiple users and for each of them you wanted to load profile, but if you have single record it won't change anything.
Additionally instead of:
$author = User::where('id', $id)->with('profile')->get();
you should rather use:
$author = User::with('profile')->find($id);
because you expect here single user.
$users = User::with('profile')->find($id);
Your model should be like this.The User_id on the profile table and id on the user table
public function profile()
{
return $this->hasOne('App\AuthorProfile', 'user_id','id');
}

How to get a random model with at least N related of multiple `hasmany` models

I am trying to combine two features:
- getting a random model
- ... but only if it has at least 1 related model
my URL is entity/random
and the below code works well:
if ($entityid == 'random') {
$random = Entity::all()->random(1);
return Redirect::to(trans('routes.entities') . '/' . $random->id);
}
Now, my Entity model has two relations defined:
public function comments()
{
return $this->hasMany('App\Models\Comment', 'entity_id');
}
public function sources()
{
return $this->hasMany('App\Models\Source', 'entity_id');
}
Having them defined, I can get the number of related comments by $object->comments->count() or sources by $object->sources->count().
My database is MySQL.
The majority of my Entities have NO comments nor sources.
Inspired by Laravel Querying Relations Model::has('relation') doesn't work
i was able to get a random model with at least 2 comments:
$random = Entity::has('comments', '>=', DB::raw(2))->get()->random(1);
// produces an Entity with at least 2 comments
TO DO
How to pick a random model only if at least one of two relations count (sources OR comments) are at least 2.
Maybe sth like orHas exists?
Yes, there is an orHas method.
You can use it like so:
$random = Entity::has('comments', '>=', 2)->orHas('sources', '>=', 2)->get()->random(1);
A couple other notes:
The DB::raw() syntax is not needed for the has() statements. There used to be a bug for sqlite databases that needed this syntax, but that has been resolved since Laravel 4.1.25.
Additionally, you may want to change how you get your random entity. With your current code, you're going to retrieve every record that meets the criteria, and create a full Entity object for each one. The more entity records you have, the slower this code is going to get. I would suggest something like this:
$id = Entity::has('comments', '>=', 2)->orHas('sources', '>=', 2)->lists('id')->random(1);
$random = Entity::find($id);
First, you use the lists() method to get all the ids of the entities that match the conditions. As of Laravel 5.2, lists() returns a collection. Use the random() method on that collection of ids to pick one id to get. Then, find() that one id, so only one Entity object is created.

Doctrine and MySQL

I have few questions about Doctrine and MySQL working together. I don't understand it in 100%
I read somewhere that Doctrine can cooperate with MySQL DB. How it happens?
How do I load my DB?
How do I operate on my MySQL tables via doctrine (I'm no thinking about creating new ones)?
Does Doctrine save automatically changes to database?, if not then how to?
Some sample of code would be great. I don’t care too much about language can be in PHP, Yaml and others.
a) please specify more what you maen with "load DB". Doctrine is an ORM.
check here docs:
http://www.doctrine-project.org/projects/orm/1.2/docs/hu (check cookbook)
b) operations with tables with Doctrine are with DQL, example:
$q = Doctrine_Query::create()
->from('User u')
->leftJoin('u.Phonenumbers p');
$q->execute(); //you get a doctrine collection to iterate results of query
c)NO you need to save the object
$account = new Account();
$account->name = 'test 1';
$account->amount = '100.00';
$account->save();
here is account class
class Account extends Doctrine_Record
{
public function setTableDefinition()
{
$this->hasColumn('name', 'string', 255);
$this->hasColumn('amount', 'decimal');
}
}