Is there any way to cast a relationship table attribute in laravel? - laravel

I have a users model with a carts function that returns all carts detail after joining three tables. I would like to convert an attribute to an array which is a JSON type.
Example: I have four table users, carts, item_detail_informations, and item_details tables where item_details table picture column is a JSON type. I want to convert picture JSON data to an array.
My carts function is like this.
public function carts()
{
return $this->hasMany('App\Models\Cart')
->join('item_detail_informations', 'carts.item_detail_information_id','=','item_detail_informations.id')
->join('item_details', 'item_detail_informations.item_detail_id','=','item_details.id')
->join('items', 'item_details.item_id','=','items.id')
->select('carts.user_id','carts.item_detail_information_id','item_detail_informations.size','item_detail_informations.price','item_detail_informations.item_detail_id', 'item_details.picture','item_details.item_id')
;
}
I am trying to cast picture attribute like this.
protected $casts = [
'item_details.picture' => 'array',
];
But it's not working. Is there any way to convert the picture attribute to JSON?

Remove all joins in carts method(instead use eager loading via with). And cast attribute in the ItemDetail model. it will automatically picked up when you call carst method. Hope it will help you

You need to use eager loading instead

Related

How can I get the data inside my notifications from within my Controller?

I'm trying to get the numbers of records from my notifications, where the candidate_user_id column from inside the data attribute is the same as the UserId (Authenticated User).
After I dd, I was able to get the data from all of the records in the table by using the pluck method (Line 1). I then tried to use the Where clause to get the items that I need
but this just didn't work, it was still returning all of the records in the table.
DashboardController.php:
public function index()
{
$notifications = Notification::all()->pluck('data');
$notifications->where('candidate_user_id', Auth::user()->id);
dd($notifications);
}
Here is a partial screenshot of the data that is being plucked.
How can I get the data from this, in a way like this ->where('candidate_user_id', Auth::user()->id);?
If data was a JSON field on the table you could try to use a where condition to search the JSON using the -> operator:
Notification::where('data->candidate_user_id', Auth::id())->pluck('data');
Assuming you only want this data field and not the rest of the fields, you can call pluck on the builder directly. There isn't much reason to hydrate Model instances with all the fields to then just pluck a single field from them if it is just a table field, so you can ask the database for just the field you want.
The data in the data field is a json string, so you can tell Laravel to automatically cast it as an array using the $casts property on each of the models that is notifiable.
For instance, if you have a User model which uses the trait (ie has use Notifiable), add this:
protected $casts = [
'data' => 'array',
];
If you want to access all notifications for the auth user.
$user = auth()->user();
dd($user->notifications->pluck('data'));
If you really want to do in your question way, here is how.
$notifications = Notification::all()->pluck('data');
$notifications = $notifications->where('candidate_user_id', Auth::user()->id)
->all();
This assumes you that you did not modify the default laravel notifications relationship and database migration setup. If you have modified some of the default ones, you need to provide how you modify it.

Laravel: retrieving one item from a relationship

I am using Laravel Eloquent to retrieve data from the database.
I want to get the related data as an object not an array ( whats inside the texts table), so it is easier to work on the data on the blade file. This is my code I tried using first() but it doesn't work
Icon::with(["texts" => function($query) use ($language){
$query->where("language_id",$language->id)->first();
}, "texts.language"])->get();
How to Acheive it?
You could create an accessor function that provides a shorthand attribute to the required value.
In your Icon class:
public function getTextAttribute() {
// You'd only have to provide the $language somehow.
return $this->texts()->where('language_id', $language->id)->first();
}
Elsewhere, like in Blade, when you're using an Icon you can then use:
{{$icon->text}}

sort laravel eloquent by custom (appended) attribute

I have a model with a custom attribute like this
public function getOpenStatusAttribute()
{
//some logic...
//returns '1-order' or '2-pre-order' or '3-closed'
}
Now i want to sort the collection in the eloquent query. I use order by name etc.. those are columns in the table but i want to order it by the custom attribute first, and then by name etc..
is it possible to do this in the query? or do i have to loop the collection and do some resorting ?
ok so the solution is:
->sortBy(['open_status'])->sortBy(['name']);
after the ->get()
hope it can help someone in the future

Adding data to an eloquent collection?

Im getting various data out of my database.
Product::with('users');
I also have toe execute a complex raw query to get back some information. This is returned as an array.
In my method I would like to get products with users and then add on the data from my raw query to this collection, but this data comes back as an array. Something like:
Product::with('users');
Product->extraData = $rawQuery;
How can I add the raw query output to my Product Collection?
By using Eloquent Facade like Product:: you will get an Eloquent Model object as a result or an Eloquent Collection object as a result, including results retrieved via the get method or accessed via a relationship.
Now, if i understand correctly, you need to add a single extraData property to Eloquent Collection model alongside with Collection items? Or you need to add extraData for each Product ?
If you need to add additional property to Eloquent Collection object, maybe it is a good idea to use a Custom Collection. Please read this section: http://laravel.com/docs/5.1/eloquent-collections#custom-collections .
<?php namespace App;
use App\CollectionWithExtraData;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function newCollection(array $models = [])
{
return new CollectionWithExtraData($models);
}
}
And maybe your CollectionWithExtraData can have let's say a
public function setExtraData() {
}
or
public $extraData = array();
If you need extraData for each Product Eloquent Model, just create a new attribute within your Eloquent Model, make it public and set your extra data when needed. Make use of setExtraData() method and $extraData property from above

Replace the column name in the magento collection while loading it

I have a custom module and I am loading a collection like following
$collection = Mage::getModel('module/product')->getCollection()
->addFieldToFilter('sku',$sku);
There is field named as prod_id in the database. Can I get this as entity_id while loading the collection?
If yes. Please help how to do this.
First of all all
addAttributeToFilter() is used to filter EAV collections.
addFieldToFilter() is used to filter Non-EAV collections.
EAV-models are for example product, customer, sales, etc so you can use use addAttributeToFilter() for those entities.
addFieldToFilter() is mapped to `addAttributeToFilter()` for `EAV` entities. So you can just use `addFieldToFiler().`
You can have a look in app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php where the Mapping is done:
public function addFieldToFilter($attribute, $condition = null) {
return $this->addAttributeToFilter($attribute, $condition);
}
If you are using custom module then you can directly use addFieldToFilter() with your column name
Like
$collection = Mage::getModel('module/model')->getCollection()
->addFieldToFilter('column_name',$data);
Let me know if you have any query

Resources