Laravel QueryBuilder where clause with user info on other model - laravel

I have a Model ImageRequest that is related to my User model like this:
public function user()
{
return $this->belongsTo('App\User');
}
An my User model like this:
public function imageRequests()
{
return $this->hasMany('App\ImageRequest');
}
Now I use this package to build my filterable query to fetch all ImageRequests:
spatie/laravel-query-builder
this is what my query looks like:
$query = QueryBuilder::for(ImageRequest::class)
->with(['requestTypes'])
->allowedIncludes('requestTypes')
->orderByRaw("FIELD(status , 'new') desc")
->orderBy('functional_id', 'asc')
->allowedFilters(
'id',
'pv_number',
'created_at',
Filter::scope('starts_between'),
'location_of_facts',
'train_nr',
'status',
'result_of_search',
Filter::custom('type', RequestTypeFilter::class)
);
I need to add a where clause for the User model something like this:
->where('zone', Auth::user->zone);
But it says:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'zone' in 'where clause' (SQL: select count(*) as aggregate from image_requests where zone = a)

Please look into this code, Here I added a whereHas instead for where. so it will take only matching records to user table for desired zone.
hope it helps..
$query = QueryBuilder::for(ImageRequest::class)
->with(['requestTypes'])
->whereHas('user'=>function($q){
$q->where('zone', Auth::user->zone);
})
->allowedIncludes('requestTypes')
->orderByRaw("FIELD(status , 'new') desc")
->orderBy('functional_id', 'asc')
->allowedFilters(
'id',
'pv_number',
'created_at',
Filter::scope('starts_between'),
'location_of_facts',
'train_nr',
'status',
'result_of_search',
Filter::custom('type', RequestTypeFilter::class));
Please have try this, used direct join query.
$query = ImageRequest::selectRaw('column1,column2')
->join('user', function($join){
$join->on('ImageRequest.user_id','=','user.id');
})
->leftJoin('request_types', function($join){
$join->on('request_types.image_request_id','=','image_request.id')
})
->where('user.zone', Auth::user->zone)
->orderByRaw("FIELD(status , 'new') desc")
->orderBy('functional_id', 'asc')
->allowedFilters(
'id',
'pv_number',
'created_at',
Filter::scope('starts_between'),
'location_of_facts',
'train_nr',
'status',
'result_of_search',
Filter::custom('type', RequestTypeFilter::class)
);

Related

Laravel 8 eager loading, how to access subquery fields

This is working:
$clients = Client::with([
'contacts' => function ($query) {
$query
->select('client_id', 'first_name', 'last_name')
->where('contact_type_id', '=', 1);
}])
->orderBy('client_name')
->get(['id', 'client_name', 'city', 'state']);
dd($clients);
However, I'm unsure of how to access first_name and last_name on the subquery. They're showing up in the "relations" object in the dump, but in my mind I'm envisioning a dataset that I would access like,
$client->first_name, etc.
When I try to add the fields to the get() method at the end, it doesn't recognize them, so I'm doing something wrong, or I need to access the subquery fields differently.
When you are eager loading the relationships, you are just preloading them.
If your relationship is defined as hasMany (which seems to be the case here, a Client hasMany Contact), then you'll always get a collection from eager loading.
If you defined another relationship in your model in order to get only one result, for instance:
public function contact()
{
return $this->hasOne(Contact::class)->where('contact_type_id', 1)->latest('id');
}
Your new relationship contact would return only one result:
$clients = Client::with('contact')
->orderBy('client_name')
->get(['id', 'client_name', 'city', 'state']);
foreach($clients as $client){
dd($client->contact->first_name);
}
// each Client of $clients would have a ->contact relationship
You should add field id to select() method in subquery and field contact_id to get() method
$clients = Client::with(['contacts' => function ($query) {
$query->select('id', 'client_id', 'first_name', 'last_name')->where('contact_type_id', '=', 1);
}])
->orderBy('client_name')
->get(['id', 'client_name', 'city', 'state', 'contact_id']);
foreach ($clients as $key => $client) {
dd($client->contacts->first_name);
// Or
dd($client->contacts()->first()->first_name);
}

how to select specific fields from the tables in laravel

This works but it gives all the fields of account table but only few are required.
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account'
])
->get();
This gives account: null
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account'=> function ($query) {
$query->addSelect('id', 'account'); // if this line is commented, all the fields are returned but I just need few fields.
}
])
->get();
Member model:
public function account()
{
return $this->hasOne(Account::class);
}
Account model:
public function member()
{
return $this->belongsTo(Member::class);
}
How can I get only the required fields of account table?
You can define the relationship and set it to give you specific columns like this.
on Member model
public function account()
{
return $this->hasOne(Account::class)->select(['id', 'account']);
}
You can try to define required fields in with:
$data = Loan::select('*')
->with([
'member' => function ($query) {
$query->addSelect('id', 'name');
},
'member.account:id,number'
])
->get();
Your are close you just need to select the foreign key column that points to your account model , I guess it would be account_id, So you basically need to select 3 columns from your table which are select(['id', 'name','account_id'])
$data = Loan::with(['member' => function ($query) {
$query->select(['id', 'name','account_id'])
->with(['account'=> function($query){
$query->select(['id','name']);
}]);
}])
->get();
So if you have another nested relation account -> type and you need specific columns from type so you need to select the foreign key column from accounts models as
with(['account'=> function($query){
$query->select(['id','name','type_id'])
->with(['type'=> function($query){
$query->select(['id','name']);
}]);
}]);

How can I use this mysql query to laravel 5.2?

I want to use below sql query into laravel 5.2
SELECT * FROM `products` WHERE soundex(`products`.`name`)=soundex('Neckholder Creme');
I Have tried here like
return $query->select([ 'products.slug', 'products.id', 'sku', 'name', 'regular_price', 'sale_price', 'sale_from', 'sale_to', 'stock_status', 'product_type', 'featured_image_id' ])
->with('media_featured_image')
->with('categories')
->where('products.product_type', '<>', 'variation')
->where('products.status', 'publish')
->where(function($query) use ($keyword){
foreach($keyword as $k){
$query->where('soundex(products.name)',soundex($k));
}
})
->paginate(120);
But it gives an error like below and having issue because of `` in column name
Column not found: 1054 Unknown column 'soundex(products.name)' in 'where clause' (SQL: select count(*) as aggregate from `products` where exists (select * from `categories` inner join `category_product` on `categories`.`id` = `category_product`.`category_id` where `category_product`.`product_id` = `products`.`id` and `categories`.`slug` <> shoparchiv) and `products`.`product_type` <> variation and `products`.`status` = publish and (`soundex(products`.`name)` = C352 and `soundex(products`.`name)` = J520))
How can I use in Laravel ? Any help will be appreciated.
Thanks
If you need just basic query then you can use DB::raw (documentation)
select(DB::raw('SELECT * FROM products WHERE soundex(products.name)=soundex("Neckholder Creme")'));
Or you can use whereRaw in eloquent and use it in your existing query (documentaion)
return $query->select([ 'products.slug', 'products.id', 'sku', 'name', 'regular_price', 'sale_price', 'sale_from', 'sale_to', 'stock_status', 'product_type', 'featured_image_id' ])
->with('media_featured_image')
->with('categories')
->where('products.product_type', '<>', 'variation')
->where('products.status', 'publish')
->where(function($query) use ($keyword){
foreach($keyword as $k){
$query->whereRaw("soundex(products.name) = '".soundex($k)."'");
}
})
->paginate(120);
Hope it helps

How to select field in another table join by eager loading in Laravel

I got category_to_news and news_main table
category_to_news
news_id int
name varchar
title timestamp
news_main
id int
title varchar
image varchar
created_at timestamp
how to return by news_main's field and category_news's field ? I've tried this method and it's not work
$posts = Categorytonews::with(array(
'Newsmain' => function($query)
{
$query->orderBy('id', 'DESC')->select(array('title', 'id', 'created_at', 'image'));
}
))
->get( );
You need join for this because with() runs another query, so ordering there won't do the job:
$posts = Categorytonews::with('Newsmain') // get all fields from Newsmain
->join('news_main', 'category_to_news.news_id', '=', 'news_main.id') // join for ordering
->orderBy('news_main.id','desc') // order by joined field
->get('category_to_news.*'); // select only main table, you don't need joined fields
// on Categorytonews model - they will be loaded by with()
$posts = Categorytonews::with(array('Newsmain' => function($query)
{
$query->select(array('title', 'id', 'created_at', 'image'))->orderBy('id', 'DESC');
}))->get();

Ordering Results from Related Tables in Eloquent and the Session

I have the following in my Event model in Laravel 4. The reason I am using QueryBuilder and not Eloquent is I need to have links in each column header in my results table in my view, that when clicked, order the results in asc or desc based on that column.
The issue I'm having is, if I use Eloquent, it won't work as most of the data is pulled through via relationships to other tables, so Eloquent can't find the required columns/fields.
public static function getEvents($perPage = 10)
{
$order = Session::get('event.order', 'start_date.desc');
$order = explode('.', $order);
$columns = array(
'events.id as id',
'title',
'locations.city as city',
'suppliers.name as supplier_name',
'venues.name as venue_name',
'start_date',
'courses.price as course_price',
'type',
'status',
'max_delegates as availability',
'tutors.first_name as tutor_first_name',
'tutors.last_name as tutor_last_name',
'contacts.first_name as d_first_name'
);
$events = DB::table('events')
->leftJoin('courses', 'course_id', '=', 'courses.id')
->leftJoin('suppliers', 'supplier_id', '=', 'suppliers.id')
->leftJoin('locations', 'location_id', '=', 'locations.id')
->leftJoin('venues', 'venue_id', '=', 'venues.id')
->leftJoin('event_types', 'event_type_id', '=', 'event_types.id')
->leftJoin('event_statuses', 'event_status_id', '=', 'event_statuses.id')
->leftJoin('tutors', 'tutor_id', '=', 'tutors.id')
->leftJoin('delegate_event', 'delegate_event.event_id', '=', 'events.id')
->leftJoin('delegates', 'delegates.id', '=', 'delegate_event.delegate_id')
->leftJoin('contacts', 'delegates.contact_id', '=', 'contacts.id')->groupBy('events.id')
->select($columns)
->orderBy($order[0], $order[1])
->paginate($perPage);
return $events;
}
If you look at my EventsController at the getOrder method:
public function getOrder($order)
{
Session::put('event.order', $order);
return Redirect::back();
}
You can see I am storing the order in the session and then in my model using that to sort the order of results.
Is there a way to do this in Eloquent the way I need to?
You know you can just add a join() to eloquent right?
So, as an example, if you have users and each user has some blog posts (i.e. user has_many blogs), you can output an eloquent model showing username and blog title, ordered by blog title, as follows:
user::join('blogs', 'blogs.id','=','users.blog_id')
->order_by('blogs.title', 'asc')
->select(array('users.username', 'blogs.title'))
->paginate(10);

Resources