How do I add an array of pivot table data to a user? - laravel

I have a pivot table of user_activities. I already have the relationship defined in the model, for example:
$activities = User::find($id)->activities;
This returns an array of objects. I want to send the user object with the activities array.
I've tried dynamically assigning this activities array to the user object but I only get an empty object as a result ($user->activities = {}) instead of the array full of activity objects. How do I add this array of activity objects to the user object?

You may try following approach (your approach should work, related models will be loaded later on call (dynamically) but this is better, known as eager loading):
$user = User::with('activities')->find($id);
Make sure you have declared the relationship properly and have related models as well.

Related

How to get columns of a model instance in Laravel?

Can I extract a specific column for a model instance in Laravel instead of using query methods statically? more clearly, instead of writing the code below:
MyModel::select('columnName')->where('id', $model->id)->first();
can we write?
$model->select('columnName');
Well, when you grab it from a model class, it is a Eloquent Object, and it has all attributes from the database.
But if you are talking about serializing that into an array or JSON everytime, then you need to modify your $visible array ;
if you wanna transform it for a specific case, then you need to do :
MyModel::select('columnName')->where('id', $model->id)->first()->pluck('columnName');

Eloquent model setRelation generating array instead of Collection

If you are doing $instance = $model->with('categories')->find($id); and after var_dump($instance->categories) it going to return Collection of categories.
But on the project I'm working on in some heavy queries, we are not using with and getting data with a combination of GROUP_CONCAT and CONCAT, like this:
\DB::raw('GROUP_CONCAT(DISTINCT CONCAT(categories.id, ",,", categories.name) SEPARATOR ";;") as categories'),
And then we are building relations manually parsing result and creating a relationship using $instance->setRelation($relation, $data) but for some reason, it's returning an array of objects instead of Collection.
There are also option to use setRelations() and this method returning Collection but I found if you have bidirectional relations it's creating recursion and working really slow. For example: if in User model we have set $this->hasMany('Comments') and in Comments model we have set return $this->belongsTo('User'); and after when we running setRelations() to manually build relations it is create nesting models with recursion (User->Comments->User and so on).
The third option is to not use setRelation() or setRelations() and just to manually create Collection, populating it and set to model. But in such case, it will not be set as a model relation.
Any suggestions on how to build manually in the right way (to create relation is same way eloquent creating with with).
Group return collection of collection so you have to remove the keys of first collection and for that you can use values function of collection like this
$instance->setRelation('relation', $data->values()->all());
Details https://laravel.com/docs/5.6/collections#method-values

Laravel Eloquent: Access relationship of Original

In Laravel you can use getOriginal() on a model in order to get the original model (before changes since it was queried).
Now I need to access the relationship of that original model... is there a way to do that?
$item = OrderItem::where('id', $id)->with('qualification')->first();
$original_item = $item->getOriginal();
$original_item["qualification"] is not defined. I can access qualification_id though.
getOriginal() method returns array of the model's original attribute values, it is not a model itself, therefore you can not get a relationship.
So you can access the relationship using standard way: $item->qualification, that should not be affected by your changes of the parent model.

Prevent hydration model objects with eloquent

I would like to understand what happen when using the toArray () method in a case like this:
Ad::query()->with('nominations')->where(['id'=>$id])->get()->toArray();
Eloquent prevents the construction of the collection and the hydration of individual model objects and directly returns an array or eloquent first hydrates the collection and the model objects and then converts everything into an array (thus doing an extra operation)?
If the answer was the second, how can I get the first behavior with eloquent?
I specify with eloquent because it would be nice to be able to do this by continuing to refer in an abstract way to the entities without then mentioning specific database features in the code (for example the name of the tables).
Answering both your questions. The second one will happen. And you can't make Eloquent create an array, you can just convert an object or collection to an array.
Also, your query has a lot of redundant code, you could just do this:
Ad::with('nominations')->find($id)->toArray()

From within a Doctrine record class, querying for the same record from the DB overwrites the properties within that class

In one of my Doctrine record classes, I have a preSave method that performs a check. In this check, a query is done on the same table that my record belongs to. This query will fetch one record from the table, and I use the hydrated result to compare to the current record represented by the class.
In some cases, the fetched hydrated result will be the same record as the one I'm working with in the preSave check. However, when this happens, any changes that I've made to the first record are reverted once the query is completed.
Why does this happen? Is there a workaround?
Doctrine might be maintaining a single reference to the record object instance, and not creating a whole new instance in your preSave() method. So when the object is hydrated, any other variables of the same type in your code are 'refreshed'.
To verify this, inspect the object ID's of variables in your code using spl_object_hash() function.
Without seeing your code, workaround suggestions can vary, but one possible workaround is to hydrate an array in preSave():
$query = Doctrine_Query::create()
->select('foo')
->from('Bar b')
->where('b.id = ?', $id);
$results = $query->execute(array(), Doctrine::HYDRATE_ARRAY);
You will lose the ability to use the result as an object, but you will be able to use the contents of the array for comparisons.

Resources