I have array of collections. In collections I have relation. How I can use whereIn in these relations?
$arrayCollections = $category->products;
$arrayCollections = $arrayCollections->character->whereIn('id', [1,2,3,4]); //I need use whereIn in character relation. I get error: Property [character] does not exist on this collection instance.
foreach($arrayCollections as $product) {
.... //but in foreach I can use $product->character
}
Relation in product model::
public function character()
{
return $this->hasMany('App\Models\ProductCharacter');
}
Try this:
$characters = $category->products()->character()->whereIn('id', [1,2,3,4])->get();
foreach($characters as $character) {
// $character
}
You seem to need an indirect relationship. The best way to get this is by using hasManyThrough
In your Category model
public function characters() {
return $this->hasManyThrough(Character::class, Product::class); // Has many characters through products
}
Then you can directly do:
$characters = $category->characters()->whereIn('id', [ 1, 2, 3, 4 ])->get();
what about this ? I added first() :
$characters = $category->products()->first()->character()->whereIn('id', [1,2,3,4])->get();
foreach($characters as $character) {
// $character
}
You can try this
$arrayCollections = $category->products()->with('character')->whereIn('id' , [1,2,3,4])->get();
foreach($arrayCollections as $product) {}
You should use the whereHas() methode and with() method.
$arrayCollections = $category->products()
->whereHas('character', function($character){
$character->whereIn('id' , [1,2,3,4]);
})
->with('character')->get();
This will get you a collection of "products" that have "characters" attach to it that have ID in [1,2,3,4].
Related
I want to get a relation, here is my code:
OrderController.php
public function orders()
{
$orders = Order::with('packages')->OrderBy('created_at', 'DESC')->paginate();
return view('admin/orders/orders')->with(compact('orders'));
}
Order.php
function packages(){
return $this->hasMany('App\Models\Package', 'id','cart_items');
}
but the problem is cart_items contains a value like this (5,6) comma separated, how can I get relation hasMany from array?
Its's not possible by ORM need to work with mutator and accessor. Please remove packages method and try this in your Order model;
protected $appends = ['packages'];
public function getPackagesAttribute ()
{
if ($this->cart_items) {
$cart_items = explode(',', $this->cart_items);
if(count($cart_items)>0) {
return Package::whereIn('id', $cart_items)->get();
}
} return null;
}
I getting results from a query built using Eloquent (Laravel's ORM)
$query = Lawyer::whereHas('user', function($q) use ($request) {
$q->where('is_active', true);
});
$result = $query->get()
I would like to pass the results I get throught a trasformer class LawyerTransformer extends TransformerAbstract{} to add some data to the results.
When I try this :
$this->collection($query->get(), new LawyerTransformer())
I have the following issue : Method [collection] does not exist.
How can I transform all the results using a transformer ?
You could use the transform method on the collection instance to achieve something like that here is an example that will increment all values in an array by 1;
$collection = collect([1, 2, 3]);
$collection->transform(function ($item, $key) {
return (new IncrementTransformer)->transform($item);
});
And the transfomer class
class IncrementTransformer
{
public function transform($item)
{
return $item += 1;
}
}
You could probably write this a little cleaner but you get the basic idea.
I was hoping I could do this on one line:
$users = [];
$rawUsers = User::select('id','first_name','last_name')->where('company_id',Auth::user()->company_id)->get();
foreach($rawUsers as $u) {
$users[$u['id']] = $u['first_name'].' '.$u['last_name'];
}
I see the Collection class has a ->map function which would let me do the concatenation, but I don't know how to get the results indexed by id. Is there a way to do what I want?
You can do this using lists method on the query:
User::select(DB::raw('concat(first_name," ",last_name) as full_name'), 'id')->lists('full_name', 'id');
// returns array(id => full_name, ...)
Or use accessor on the model and lists on the collection:
// User model
public function getFullNameAttribute()
{
return $this->attributes['first_name'].' '.$this->attributes['last_name'];
}
// then on the collection call lists:
$usersRaw = User::where(...)->get()->lists('fullName','id');
Being new to this framework faced a problem that the resultset is not paginated with the use of standart ->paginate() method if I want to get the result with relations. What is the best approach to achieve the desired ?
Here is my method :
public function findAll($perPage = 15, $order = 'ASC', $orderBy = 'id')
{
$users = User::orderBy($orderBy, $order)->with('permissions','companies')->paginate($perPage);
$users = $users->toArray();
return $users['data'];
}
There's actually no need to convert the result object into array, so in your example you can actually do something like this in the function:
$users = User::orderBy($orderBy, $order)->with('permissions','companies')->paginate($perPage);
return $users;
Then to access the values in your view:
foreach ($users as $user){
echo $user->name;
}
I have a complex Model with multiple defined relations. In this example I would want to count the Like model and create a property named likes so it can be returned from a REST service.
Is it possible to eager load a model count into a dynamic property?
$beat = Post::with(
array(
'user',
'likes' => function($q){
$q->count();
}
))
->where('id', $id)
->first();
Assuming you are having Post->hasMany->Like relationship and you have declared likes relationship as:
class Post{
public function likes(){
return $this->hasMany('Like');
}
}
create a new function say likeCountRelation as:
public function likeCountRelation()
{
$a = $this->likes();
return $a->selectRaw($a->getForeignKey() . ', count(*) as count')->groupBy($a->getForeignKey());
}
now you can override __get() function as:
public function __get($attribute)
{
if (array_key_exists($attribute, $this->attributes)) {
return $this->attributes[$attribute];
}
switch ($attribute) {
case 'likesCount':
return $this->attributes[$attribute] = $this->likesCountRelation->first() ? $this->likesCountRelation->first()->count : 0;
break;
default:
return parent::__get($attribute);
}
}
or you can use getattribute function as :
public function getLikesCountAttribute(){
return $this->likesCountRelation->first() ? $this->likesCountRelation->first()->count : 0;
}
and simply access likesCount as $post->likesCount you can even eager load it like:
$posts=Post::with('likesCountRelation')->get();
foreach($post as $post){
$post->likesCount;
}
NOTE: Same logic can be used for morph many relationships.
You should use the SQL Group By statement in order to make it works. You can rewrite your query like the following one.
$beat = Post::with(
array(
'user',
'likes' => function($q) {
// The post_id foreign key is needed,
// so Eloquent could rearrange the relationship between them
$q->select( array(DB::raw("count(*) as like_count"), "post_id") )
->groupBy("post_id")
}
))
->where('id', $id)
->first();
The result of likes is a Collection object with one element. I'm assuming the relationship between model Post and Like is Post hasMany Like. So you can access the count like this.
$beat->likes->first()->like_count;
I'm not tested code above but it should works.