How to use query scope in join request Laravel? - laravel

I have the following request:
$objects = Object::with("translate")->where(function ($query) use ($request) {
$query->language();
})->with('images')->with("category")->orderBy('id', 'desc')->paginate($limit);
So, in model Object there is method: translate:
public function translate()
{
return $this->hasMany("App\ObjectTranslate", "objectId", "id");
}
So, also in this model is:
public function scopeLanguage($query)
{
$languageHeader = new ModelLibrary();
return $query->where('language', '=', $languageHeader->getLanguage());
}
When I try to call scope in main request:
$query->language();
I get SQL error:
Column not found: 1054 Unknown column 'language' in 'where clause' (SQL:

You need to join the query with ObjectTranslate's table. your scopeLanguage() function will not work , since you are trying to access the column language which is not available in Object model column.
Note : With() will just eager loading, which will load the eloquent defined function, you cannot directly access their column in where clause.
Modify your scopeLanguage function
public function scopeLanguage($query)
{
$languageHeader = new ModelLibrary();
return $query->join('object_translate_table','object_translate_table.objectId','=','object_table.id')->where('object_translate_table.language',$languageHeader->getLanguage());
}
$objects = Object::with("translate","images","category")
->language()
->orderBy('id', 'desc')
->paginate($limit);
This should work
Assumin ObjectTranslate model's table name is object_translate_table and Object model's table name is object_table

Related

how to sum in subquery in laravel

i want to sum in addselect() function but it show me error.
I have 2 model as see there:
1.jewelItem model:
protected $table = 'jewel_items';
public function buyInvoice(){
return $this->belongsTo(BuyInvoice::class,'buy_invoice_id');
}
2.buyInvoice model:
protected $table = 'buy_invoices';
public function jewelsItems(){
return $this->hasMany(JewelsItems::class);
}
and every jewelItem has weight column.
my query:
$buyInvoice=BuyInvoice::addSelect(['allWeight'=>JewelsItem::whereColumn('buy_invoices.id','buy_invoice_id')->sum('weight')
])->get();
but it show me this error:
Column not found: 1054 Unknown column 'buy_invoices.id' in 'where clause' (SQL: select sum(`weight`) as aggregate from `jewel_items` where `buy_invoices`.`id` = `buy_invoice_id`)
how can i fix this without using Raw method, cause as here says "Raw statements will be injected into the query as strings" and it's vulnerable.
In newer version of laravel you can use withSum to get sum of weights for related jewelsItems
$buyInvoice=BuyInvoice::withSum('jewelsItems', 'weight')
->orderBy('jewelsItems_sum_weight')
->get();
Or in older versions you could use withCount for sum as
$buyInvoice= BuyInvoice::withCount([
'jewelsItems as allWeight' => function ($query) {
$query->select(DB::raw("sum(weight)"));
}
])->orderBy('allWeight')
->get();
you forgot use join in this subquery
JewelsItem::whereColumn('buy_invoices.id','buy_invoice_id')->sum('weight')
Instead of doing a custom count subquery, Laravel has syntaxic sugar for doing this, utilizing the method withSum(). An example of that could be.
$data = Model::query()->withSum('relation.subRelation','weight')->get();

Cant get laravel query with relationship

I have model class Post with relationship
function postanchors(){
return $this->hasMany('App\PostAnchors', 'post_id', 'id');
}
posts_anchors is simple table
id | post_id | anchor_id
Now I want to get posts if they has anchor_id = 51
$query = Post::query();
$posts = $query->with('postanchors', function ($query){
$query->where('anchor_id','=', 51);
})
error mb_strpos() expects parameter 1 to be string, object given
$posts = $query->with('postanchors')->where('anchor_id', 51)->paginate(8);
does not working too
Undefined column: 7 ERROR: column "anchor_id" does not exist LINE 1: select count() as aggregate from "posts" where "anchor_id"*
It mast be simple request. May be relationship wrong?
try below query:
$query = Post::query();
$posts = $query->whereHas('postanchors', function ($query){
$query->where('anchor_id','=', 51);
})->get();

Adding Multiple Where Clause from Model in Laravel

I am trying to clean my code up, and working on the Models
I have the following 2 tables broken down like this:
Roll Table
|id|roll_id|member_id|.......
Members table
|id|first_name|last_name|rank|
I have the following on my Roll Model
public function member()
{
return $this->belongsTo('App\Member');
}
This on my Member model
public function roll()
{
return $this->hasMany('App\Roll');
}
While the following code does return the correct results
$roll = Roll::with(['member'])
->where('status', '!=', 'A')
->get();
return ($roll);
I would like to add an extra where clause
->where('rank','<', 12)
However, I get the following error
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'member.rank'
in 'where clause' (SQL: select * from Roll where roll_id = 4 and
status != A and `mem ▶"
You can use whereHas method to filter on the relations:
$roll = Roll::with(['member'])
->where('status', '!=', 'A')
->whereHas('member', function($query) {
$query->where('members.rank', '<', 12);
})
->get();
Hope this will resolve your issue.

Laravel Repositories whereHas -- multiple

I have the following repository Products and each product can have many Categories and many Bidders
What I am trying to achieve is the following (Without Repository)
$products = Products::whereHas('categories', function ($category) {
})->whereHas('bidders', function ($bidder) {
})->get();
This works fine, however, I am trying to make it so that repositories are in place and you can still do the whereHas query, so in my repository I created a method:
public function whereHas($attribute, \Closure $closure = null)
{
return $this->model->whereHas($attribute, $closure);
}
This works well, but only if I am using one of them in my main query, whereas if I use multiple:
$products = $this->products->whereHas('categories', function ($category) {
$category->where('id', '=', 1);
})->whereHas('bidders', function($bidders) {
})->get();
I am getting the following error:
Unknown column 'has_relation'
Column not found: 1054 Unknown column 'has_relation' in 'where
clause' (SQL: select * from products where exists (select * from
categories inner join products_categories on categories.id =
products_categories.categories_id where products.id =
products_categories.products_id and id = 1) and (has_relation
= sections))
The issue I'm seeing is that its returning a collection of items on the first whereHas which means it cannot compute the second one. Any ideas to where I am going wrong?
You can pass a closure with multiple relations to whereHas
$products = $this->products->whereHas(['categories', function
($category) {
$category->where('id', '=', 1);
},'bidders' => function($bidders) {
}])->get();
It will work as expected.

Get two polymorphic relationship results together

From the Laravel documentation - if I have this many-to-many polymorphic relationship:
class Tag extends Eloquent {
public function posts()
{
return $this->morphedByMany('Post', 'taggable');
}
public function videos()
{
return $this->morphedByMany('Video', 'taggable');
}
}
So I can do this:
$tag = Tag::find(1);
$posts = $tag->posts;
$videos = $tag->videos;
How could I get all the tags relationships as one result? i.e. in a one-to-many polymorphic relationship you do this:
$tag = Tag::find(1);
$taggable = $tag->taggable;
But that doesnt seem to work for me in the many-to-many relationship - I get this SQL error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'tag_groups.'
in 'where clause' (SQL: select * from tag_groups where
tag_groups.`` is null limit 1)
You'll have to merge the results yourself:
$taggable = $tag->posts->toBase()->merge($tag->videos);
This'll return an instance of Illuminate\Support\Collection.
An Eloquent collection does not make sense in this context.
You can't get all relations in one result but you may load them all eagerly using something like this:
$tag = Tag::with(['posts', 'videos'])->find(1);
$relations = $tag->getRelations();
Here $tag->getRelations() will return an array of loaded relations so you may access one using something like this:
$posts = $relations['posts']; // Collection of Post models
$videos = $relations['videos']; // Collection of Video models
You can merge them like:
$allRelations = array_merge($posts->toArray(), $videos->toArray());
Or using merge method of Illuminate\Support\Collection (As Joseph Silber mentioned)
$allRelations = $relations['posts']->toBase()->merge($relations['videos']);

Resources