I got the following code:
$popularProducts = PopularProduct::with('product')->get();
This is how I get all of products from popular_products (contains only product_id) table with relations for products table. But I have this result:
Collection {#409 ▼
#items: array:1 [▼
0 => PopularProduct {#411 ▼
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:4 [▶]
#original: array:4 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"product" => Product {#462 ▶}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [▶]
}
]
}
I need to take only relations->product field. How can I take it?
You can do it like this
$products = PopularProduct::with('product')->get()->pluck('product');
if you like the result to be keyed you can do it like this
$products = PopularProduct::with('product')->get()->pluck('product','id');
// you can key it with **id** of the table (popularProduct) or by **id_product** of relationship (product)
if you like only to retrieve specific fields from relation you can try something like this
$products = PopularProduct::with('product:id,product_name')->get()->pluck('product','id');
You can use whereHas method (if there is a relationship between these tables)
$popular_products = Product::whereHas('products', function ($query) {
$query->where('popular_products',$ids);
})->get()
You need to iterate over the collection:
#foreach ($popularProducts as $popularProduct)
{{ $popularproduct->product->id }}
#endforeach
If you just want to get all products from the collection, use the pluck() method:
$products = $popularProducts->pluck('product');
Update
In the comments, you've said you want to get links directly from DB:
Product::has('popularProduct')->pluck('links');
This will work if you've defined the popularProduct relationship in the Product model.
Related
I'm kinda new to relations in Laravel.
When I do ddof an object, I get this:
Collection {#485 ▼
#items: array:1 [▼
0 => Menu {#484 ▼
#table: "menus"
#fillable: array:6 []
#hidden: array:2 [▶]
#connection: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:9 []
#original: array:11 []
#relations: array:2 [▼
"pivot" => Pivot {#486 ▶}
"subMenus" => Collection {#items: array:3 [▼
0 => SubMenu {#488 ▼
#table: "sub_menus"
#fillable: array:5 []
#hidden: array:2 []
#connection: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:8 []
#original: array:10 [▼
"id" => 16
"name" => "My name" <--------- this is what I need to get
"created_at" => "2018-11-20 15:19:14"
"updated_at" => "2018-11-20 20:29:34"
How can I get the namevalue from the Model SubMenu that has a relation with my dd(model) ?
In Menu I got thos relation:
public function subMenus()
{
return $this->belongsToMany('App\SubMenu', 'menu_submenu', 'menu_id', 'submenu_id')->where('estado', Define::ESTADO_ACTIVO)->orderBy('orden');
}
I tried something like:
dd($MyMenuObject->subMenus());
but not working. Tried with get(), ->submenu, etc.
EDIT: This is my data:
with dd($perfil_activo->menus); I get:
You can access it via
$model->subMenus()->first()->name;
But since $subMenus() is a many-to-many relationship, you should probably do this via a loop:
foreach($model->subMenus AS $subMenu){
$subMenu->name; // Do with as you please.
}
Edit: Since $model is also a Collection, you need to use ->first() or a loop:
$model->first()->subMenus->first()->name;
// OR
foreach($model AS $model){
$model->subMenus->first()->name;
// OR
foreach($model->subMenus AS $subMenu){
$subMenu->name;
}
}
This is all dependant on how you fetch $model; if your Query ends with a ->get() or ->all(), it will be a Collection. If it ends with ->first(), ->find(), etc, it will be a single Model.
You can list all the subMenu names on an array: or object
$names=$model->subMenus()->pluck('name'); //object
//or
$names=$model->subMenus()->pluck('name')->toArray();// to array
dd($names);
How would you change the attributes from a collection?
So the return is a Collection of Models with changed attributes, and not a Collection of arrays.
The things is, I would like to make some kinda of translation presenter, so when I get the collection I could dd($collection) and instead of 'name' it would show 'nome', also using response()->json($collection) would show the changed named.
so something like $presenterNames = ['name' => 'nome', 'id' => 'identificador']; and the names that aren't here would call normally.
Collection {#213 ▼
#items: array:2 [▼
0 => Category {#215 ▼
+timestamps: false
#fillable: array:2 [▶]
#connection: "mysql"
#table: "categories"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:3 [▼
"id" => 1
"name" => "categoria1"
"slug" => "categoria1"
]
#original: array:3 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
#hidden: []
#visible: []
#guarded: array:1 [▶]
#slugOptions: null
}
1 => Category {#219 ▶}
]
}
so basically I would like to change
#attributes: array:3 [▼
"id" => 1
"name" => "categoria1"
"slug" => "categoria1"
]
to this
#attributes: array:3 [▼
"identificador" => 1
"nome" => "categoria1"
"slug" => "categoria1"
]
Dinamicaly by using a assoc array.
Solution :
In your Model add below code.
protected $appends = ['nome'];
public function getNomeAttribute(){
return $this->attributes['name'];
}
You can access it by querying $modelObj->nome;
Do the same for all needed attributes.
This will also reflect in your JSON response.
Thanks
Reference : https://laravel.com/docs/5.7/eloquent-mutators#defining-an-accessor
I want to retrieve only the listed organisations but the the database return all the records.
you can see below a record should not be returned as a listed organisation I include below the code and my Model and The result I got from the database
$organisations = Organisation::with(['year_status' => function ($query) use ($year_id) {
$query->where(['year_id' => $year_id, 'is_listed' => 1]);
}])->get();
public function year_status()
{
return $this->hasMany('App\OrganisationYearStatus');
}
and what I got :
11 => Organisation {#630 ▼
#fillable: array:8 [▶]
#connection: "mysql"
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:14 [▼
"id" => 39
"organisation" => "Test Organisation"
"sector_id" => 1
"country_id" => 1
]
#original: array:14 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▼
"year_status" => Collection {#632 ▼
#items: []
}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
database structure :
id
organisation_id
year_id
is_listed
Make sure your relationship is well established (Organization model hasMany year_status) and that your fields are in the visible array in the YearStatus Model.
Also, the query you're using is translated to:
SELECT * FROM organizations where exists
(select * from year_status where organizaton_id = organizations.id
and year_id = $year_id and is_listed = 1)
It doesn't fetch ALL the records existing in the database, it fetches due to the relationship + the fields you've added
Note: If you want to fetch only the organization that have OrganizationYearStatus, then you should use:
Organisation::whenHas('year_status' => function ($advancedWhenHas) use ($year_id) {
$advancedWhenHas->with(['year_status' => function ($query) use ($year_id) {
$query->where(['year_id' => $year_id, 'is_listed' => 1]);
}}])->get();
You can type out ->toSql() instead of ->get() to make sure your query is the one you expect it to be
Within my view, I am displaying a value but it's showing as an object: ["Jamie Rogers"]. I want to remove the [" ... "]part.
Function:
$auditor = $audit->map(function ($user) {
return $user->name;
});
Initial structure of Audit:
Collection {#432 ▼
#items: array:1 [▼
0 => Score {#410 ▼
#table: "scores"
#fillable: array:3 [▶]
#connection: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:9 [▶]
#original: array:9 [▼
"id" => 5
"score" => 0.11
"name" => "Jamie Rogers"
"created_at" => null
"updated_at" => "2017-03-19 17:47:23"
]
#relations: array:1 [▶]
#hidden: []
#visible: []
#appends: []
#guarded: array:1 [▶]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
]
}
If I cast the value, using return (string) $user->name, it doesn't change it.
To get the first (and only) object of the collection, use the pluck method, followed by the first method:
$auditor = $audit->pluck('name')->first();
A map function is available on collection when you map on a collection it means that you want to do something with the data & return the processed data e.g you have first name & last name now in your API you want to response as full name
$collection->map(function($value, $key) {//https://laravel.com/docs/5.4/collections#method-map
return [
'full_name' => $value->firstName . ' ' . $value->lastname
]
});
In map function you pass function will get two value first is value & second is the key.
so in your case you can also do it in this way also
$collection->map(function($value, $key) {
return [
'name' => $value->name
]
})->first();
But for less coding manniL's answer is more better then me.
In pluck you can get a key value like array_column but unlike pluck works on collections only. You can also tell pluck method to what will be the key for values if you pass a second parameter the key will be the value of that column. Also like to mention pluck also return a collection object. So you can use all the methods like first on that object.
I have an Eloquent Collection just like this (dumped):
Collection {#788 ▼
#items: array:3 [▼
0 => Rating {#787 ▼
#table: "ratings"
+timestamps: false
#connection: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
#attributes: array:3 [▼
"id" => 1
"rating" => "50"
"type" => "min"
]
#original: array:3 [▶]
#relations: []
#hidden: []
#visible: []
#appends: []
#fillable: []
#guarded: array:1 [▶]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
1 => Rating {#786 ▶}
2 => Rating {#785 ▶}
]
}
In one of my views, I need to show only the Ratings with 'max' type and I am trying to filter the collection without success until now.
My tries so far:
if ($ratings && $ratings -> search('max') != false)
OR
if ($ratings && $ratings -> contains('max'))
So... What is the smart and eloquent way of achieving this?
Thanks in advance.
You can use the where method: https://laravel.com/docs/5.4/collections#method-where
$filtered_ratings = $ratings->where('type', 'max');
You could also use the filter() method on the collection.
return $collection->filter(function ($value, $key) {
if($value->type == 'max'){
return $value;
}
});