Laravel 5 - Eloquent Query - Is this possible? - sql

I want to find all of the "Posts" that have users. Users are assigned in groups and I want to find all of the "Posts" that have a particular user group. I can get the posts by name, and that have a usergroup:
$results = Post::PostBySlug("Testing")
->with('groups', 'groups.users')
->first();
This works, but, returns all of the user groups that are assigned to a particular group. I want to do it so that I can select the post, by the slug, and return all the users of a particular group. I have tried:
$results = Post::PostBySlug("Testing")
->with('groups', 'groups.users')
->where('groups.id', '=', 1);
But this did not return anything, only an unknown column. I have tried to do:
$results = Post::PostBySlug("Testing")
->with('groups AS testing', 'groups.users')
->where('testing.id', '=', 1);
But yet, no further. Can anyone suggest where I am going wrong, or suggest an alternative approach to this?

You need a query scope with the given group id.
class Post extends Model {
public function scopeInGroup($query, $group_id) {
return $query->whereHas('groups', function($query) use ($group_id) {
return $query->where('id', $group_id);
}
}
}
Then your query would be:
Post::PostBySlug('Testing')
->InGroup(1)
->with('groups.users')
->get();

Related

Laravel 7 Eloquent models - (not being able to do where outside table) Unable to find column on businessDeveloper.user_id, select * from opportunities

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'businessDeveloper.user_id' in 'where clause' (SQL: select * from opportunities where businessDeveloper.user_id = 3)
Hello, I'm using Laravel 7 and eloquent models for a school project. We were told not to use joins and besides making a custom JSON string with the formatted data which will take a lot of work since I have the same problem for other functionalities as well. I got no clue how to solve my problem. The tables are like this:
Opportunities(business_developer_id FK) belongTo-> businessDevelopers(user_id FK) belongTo-> user
So I try to show all opportunities for a logged in business developer. But this doesn't seem to work:
public function qryOpportunities()
{
$opportunities = Opportunity::where('businessDeveloper.user_id', Auth::id())->with('businessDeveloper.user', 'consultantOpportunity.consultant.user', 'contactPerson', 'customer', 'headOfDepartment.user')->get();
return $opportunities;
}
A solution to show all opportunities from the logged-in business developer is much appreciated. Thanks in advance.
Try ->whereHas() :
public function qryOpportunities()
{
$opportunities = Opportunity::whereHas('businessDeveloper', function($q) {
$q->where('user_id', Auth::id());
})
->with('businessDeveloper.user', 'consultantOpportunity.consultant.user', 'contactPerson', 'customer', 'headOfDepartment.user')
->get();
return $opportunities;
}
You can check the docs of whereHas() here: https://laravel.com/docs/7.x/eloquent-relationships#querying-relationship-existence
I suggest you use this code:
public function qryOpportunities()
{
return Opportunity::query()
->whereHas('businessDeveloper', function($query) {
$query->where('user_id', Auth::id());
})->with('businessDeveloper.user', 'consultantOpportunity.consultant.user', 'contactPerson', 'customer', 'headOfDepartment.user')
->get();
}

How to Query if Multiple Columns Reference to the Same Table

I am facing an issue here. I have a table called application and it will record who requests the application, who approves it, and who rejects it. The issue is the Requestor_id, Approver_id and Rejector_id are references to the same table. How can I query for the requestor_name, approver_name, and rejector_name in Laravel
Application table
Requestor_id ( reference to user id)
Application_Status
Module_id
Approver_id ( reference to user id)
Rejector_id ( reference to user id)
created_at
updated_at
Below is what I have tried but it can only retrieve for the requestor name
$Approval_Logs = DB::table('application')
->select('application.id','application.Application_Status', 'users.name','application.Approver_id','application.Rejector_id', 'ems_application.Request_Category','application.updated_at')
->join('ems_application', 'ems_application.Application_id', '=', 'application.id')
->join('users', 'users.id', '=', 'application.requestor_id')
->whereIn('application.Application_Status',['approved','rejected'])
->get()
->toArray();
I hope I can receive some hints from you. Thanks in advance!
You may use aliases in your joins also.
$Approval_Logs = DB::table('application')
->select(
'application.id',
'application.Application_Status',
'application.Approver_id',
'approver.name as approver_name',
'application.requestor_id',
'requestor.name as requestor_name',
'application.Rejector_id',
'rejector.name as rejector_name',
'ems_application.Request_Category',
'application.updated_at'
)
->join('ems_application', 'ems_application.Application_id', '=', 'application.id')
->join('users as requestor', 'requestor.id', '=', 'application.requestor_id')
->join('users as approver', 'approver.id', '=', 'application.approver_id')
->join('users as rejector', 'rejector.id', '=', 'application.rejector_id')
->whereIn('application.Application_Status',['approved','rejected'])
->get()
->toArray();
I am not completely familiar with your application, however you may want to utilize left_join instead of join for the approver and rejector joins in the event that there was not an approver or rejector.
If you would like to do it the "Laravel" way. I would create a model called Application and create relations
class Application extends Model {
public function requestor(){
return $this->belongsTo(Users::class, 'requestor_id');
}
public function approver(){
return $this->belongsTo(Users::class, 'approver_id');
}
public function rejector(){
return $this->belongsTo(Users::class, 'rejector_id');
}
}
Then in your controller, you can run the following query:
$application = Application::whereHas('requestor', function($query) {
$query->where('first_name', 'John');
})->whereHas('approver', function($query) {
$query->where('first_name', 'Peter');
})->whereHas('rejector', function($query) {
$query->where('first_name', 'Michael');
})->get();
That should query the users table for the first names. I don't know how efficient this will be, but give it a try;

Laravel Eloquent - where relationship field does not equal

I thought this would be fairly simple but it's not playing ball currently.
I have 2 tables for this question, 'applications' & 'application_call_logs'.
This query needs to return all from the applications table where the latest call log doesn't have a status of X.
Here's the current query:
$query = Application::query();
$query->where(function($query) {
$query->whereDoesntHave('call_logs');
$query->orWhereHas('latest_call_log', function($q) {
$q->where('status', '!=', 'not interested');
});
});
return $query->get();
This should return all rows that either have no call logs, or where the latest call log doesn't have the status field equaling a specific string.
This here:
$q->where('status', '!=', 'not interested');
Seems to have no affect if the call_logs has more than 1 row, even though I'm querying the latest relationship. I've also verified the latest is returning the correct latest record.
The two relationships in the Application model are:
public function call_logs()
{
return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id');
}
public function latest_call_log()
{
return $this->hasOne('App\ApplicationCallLog', 'lead_id', 'id')->latest();
}
Checked the SQL generated:
select * from `applications` where (not exists (select * from `lead_call_logs` where `applications`.`id` = `lead_call_logs`.`lead_id`) or exists (select * from `lead_call_logs` where `applications`.`id` = `lead_call_logs`.`lead_id` and `status` != ?))
there is a solution around should be good for this situation:
i think that this line has the week point of the code:
return $this->hasOne('App\ApplicationCallLog', 'lead_id', 'id')->latest();
this should be hasMany, but you use hasOne to limit the result to one.
and if you tried:
return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id')->latest()->limit(1);
it simply won't work, because the result will be limited to ApplicationCallLog for all of the results ....
will, there is a package staudenmeir/eloquent-eager-limit that is made especially for this situations:
composer require staudenmeir/eloquent-eager-limit:"^1.0"
class Application extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
public function latest_call_log()
{
return $this->hasMany('App\ApplicationCallLog', 'lead_id', 'id')->latest()
->limit(1);
}
}
class ApplicationCallLog extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
}
using this package will limit ApplicationCallLog for every result in your query not one for all of the result, and that will have the same effect for hasOne ....
with this minor enhancement, i think:
$q->where('status', '!=', 'not interested');
will work ...
more about eloquent-eager-limit package in:
https://github.com/staudenmeir/eloquent-eager-limit

Laravel/SQL: How to fetch data from multiple table in a single query? that too using 'where'

Working on a search functionality on Laravel App(Blog/Posts).
There are multiple types of posts (each having a separate table in the database)
Like Business posts, Social Life posts etc..
Below is the search function on SearchController
class SearchController extends Controller
{
public function search(Request $request, $query = null)
{
if($query == null)
return redirect()->route('home');
$search = Business::where([['title','like','%'.$query.'%'],['status','=',1]])
->orWhere([['description','like','%'.$query.'%'],['status','=',1]])
->paginate(10);
return view('front.search',[
'results' => $search,
'query' => $query
]);
}
}
So basically my question is how to add other types of Post's table also?
My main motive is that when someone searches for anything, the result should be fetched from all types of posts table(business, nature, life & so on..).
You have to maintain common id in both the table
NOTE: Join is the preferable method
$querys = DB::table('Business')->where([['Business.title','like','%'.$query.'%'],['Business.status','=',1]])
->orWhere([['Business.description','like','%'.$query.'%'],['Business.status','=',1]]);
$querys->join('socialtable','socialtable.userid','=','Business.userid');
// Just join the social table
$querys->where('socialtable.title', 'like','%'.$query.'%');
$result = $querys->paginate(10);
If you have a model called Book, like this:
class Book extends Model
{
/**
* Get the author that wrote the book.
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
Then you can retrieve all of your books with authors like this:
$books = App\Book::with(['author'])->get();
Check out Eager loading from Laravel documentation.
Just add table name before every field
$querys = DB::table('Business')->where([['Business.title','like','%'.$query.'%'],['Business.status','=',1]])
->orWhere([['Business.description','like','%'.$query.'%'],['Business.status','=',1]]);
$querys->join('socialtable','socialtable.userid','=','Business.userid');
// Just join the social table
$querys->where('socialtable.title', 'like','%'.$query.'%');
$result = $querys->paginate(10);

Select specific columns of table and relation in laravel

Lets consider I have a Model User and another Model Employee
Now I want to pluck only some fields of Employee model such as salary, id, emp_id along with some columns of User model such as name,id.
$employee = Employee::with('user:id,name')
->where('department', $request->department)
->get(['id', 'emp_id', 'salary']);
When I execute this it will return id,emp_id,salary data but for user:name,id it will return null
How can I also specify user:id,name in get() ?
You can either load the full model or only some fields of it. To only load some fields, use select(). It also works within the relationship eager loading query:
$employees = Employee::with(['user' => function ($query) {
$query->select(['id', 'employee_id', 'name']);
}])
->where('department', $request->department)
->select(['id', 'emp_id', 'salary'])
->get();
use select() method from Query bulider:
$employee = Employee::with('user') // or users <---
->select(['id', 'emp_id', 'salary', 'users.id AS user_id', 'users.name AS username'])
->where('department', $request->department)
->get();