How to optimize this query using model in Laravel - laravel

Actual Requirement.
Select * from User, Student_basicinfo,Student_programs where
User.id=student_basicinfo.student_id,user.id=student_programs.student_id;
I want to use this query with model approach but i don't know how.
there 3 different tables
student_id is primary in user table but in other tables is as foreign key.
public function getdata()
{
$users= DB::table('Student__Basicinfos')
->join('Student__Programs', 'Student__Basicinfos.student_id', '=', 'Student__Programs.student_id')
// ->join('Student__Academics', 'Student__Basicinfos.student_id', '=', 'Student__Academics.student_id')
//->join('Upload', 'Student__Basicinfos.student_id', '=', 'Upload.student_id')
->select ('Student__Basicinfos.student_id','student__Basicinfos.student_name','student__Basicinfos.father_name',
'student__Basicinfos.gender','student__Basicinfos.domicile_province','student__Basicinfos.present_address','student__Basicinfos.present_mobile',
'student__Basicinfos.student_email','student__Basicinfos.created_at',
'Student__Programs.student_status','Student__Programs.program1','Student__Programs.program2','Student__Programs.awaiting_result')
->orderByRaw('student_id DESC')
->get();
return view('alldata',compact('users'));
}

Related

Laravel Lumen eloquent left join returns joined table data rather than primary able data

I have two tables company and courses table
The table has the following fields
companies table
id, full_name, email, deleted_at
and courses table
courses table
id, company_id, course_name,deleted_at
Now i would like to retrieve all courses which company is not deleted. So in my controller i have added
public function index(Request $request){
$query = Courses::query();
$query = $query->leftJoin('companies','companies.id','=','courses.company_id');
$query->whereNull('companies.deleted_at');
if($request->get('filter_name')){
$query = $query->where('courses.name', 'like', '%' . $request->get('filter_name') . '%');
}
return response()->json($query->paginate($request->get("perPage")));
}
When i run the above it returns companies data rather than courses. Where am i going wrong or what am i missing out?
If you have use eager loading in both of your model, you can use this kind of approach.
$all_course = Courses::with(['company', function($query) {
return $query->whereNotNull('deleted_at');
}])->get();
As you can see, I query in the Courses model to return all the courses but I added some filter in the company relationship. where in I used whereNotNull to get only the company that's not deleted.

One to Many Relationship in Laravel 5.5

I'm having trouble with a one-to-many relationship in Laravel 5.5.
I have two tables, one for blog posts and one for authors. The posts table has an author_id column and it's populated with valid author IDs for each blog post. author_id is defined as a foreign key in the posts table migration.
When I load a view that uses the query the author is null because the author_id isn't being included in the generated query.
Post model:
public function author(): BelongsTo
{
return $this->belongsTo(Author::class);
}
I also tried explicitly listing the keys with the same result:
return $this->belongsTo(Author::class, 'author_id', 'id');
Post repository:
public function getPostBySlug(string $slug)
{
return $this->model
->select(
'posts.title',
'posts.contents',
'posts.published_at'
)
->with(['author:first_name,last_name,slug'])
->where('posts.slug', '=', $slug)
->whereNotNull('posts.published_at')
->first();
}
Generated query:
select `first_name`, `last_name`, `slug`
from `authors` where `authors`.`id` in ('')
and `authors`.`deleted_at` is null
You didn't select the posts.author_id so without the author_id the relationship couldn't be made, either select * or exclude the select statement or include posts.author_id in your select statement, for example:
$this->model
->select(
'posts.author_id',
'posts.title',
'posts.contents',
'posts.published_at'
)
// rest of the code ...
The foreign key (posts.author_id) has to be available to build the relationship with authors.
Try this
$users = DB::table('posts')
->leftJoin('authors', 'authors.id', '=', 'posts.user_id')
->select('posts.author_id','posts.title','posts.contents','posts.published_at',
'authors.first_name','authors.last_name','authors.slug')
->where('posts.slug', '=', $slug)
->whereNotNull('posts.published_at')
->first();
tray the ralation in the following way
:
return $this->belongsTo('namespace\author');
or reverse way
return $this->hasMany('namespace\author');

Laravel eloquent table joined to itself, how to get 1 array with all values

I am using a table employee that is joined to itself for the manager.
Employee
id
name
manager_id (FK to Employee)
I am using the following model for Employee:
public function my_employees()
{
return $this->hasMany('App\Employee', 'manager_id');
}
public function my_manager()
{
return $this->belongsTo('App\Employee', 'manager_id');
It is working fine because I can use the my_employees function on an employee and it will get me all the records linked to this employee.
Now I would like to get a table with all the employees where the column manager_id is replaced by manager_name. How can I achieve this with Eloquent?
Not using Eloquent, I do:
$employee = DB::table('employee')
->select('employee.id', 'employee.name', 'employee.manager_id','manager.name AS manager_name')
->join('employee AS manager', 'employee.manager_id','=','manager.id');
This gets me of course what I want but I would like to understand how to do it with Eloquent only.
Thanks.
Exactly the same way.
$employees = Employee::select('employee.id', 'employee.name', 'employee.manager_id', 'manager.name AS manager_name')
->join('employee AS manager', 'employee.manager_id', '=', 'manager.id')
->get();
You could also do this shown below. But then you need to access the manager name from the relationship object.
$employees = Employee::with('my_manager')->get();
foreach($employees as $employee) {
echo $employee->my_manager->name;
}
Edit
You can add any constraint to the eager loaded relationship.
$employees = Employee::with(['my_manager' => function($query) {
$query->select('manager_id', 'name');
}])->get();

Laravel 4/5, order by a foreign column

In Laravel 4/5 how can order a table results based in a field that are connected to this table by a relationship?
My case:
I have the users that only store the e-mail and password fields. But I have an another table called details that store the name, birthday, etc...
How can I get the users table results ordering by the details.name?
P.S.: Since users is a central table that have many others relations and have many items, I can't just make a inverse search like Details::...
I would recommend using join. (Models should be named in the singular form; User; Detail)
$users = User::join('details', 'users.id', '=', 'details.user_id') //'details' and 'users' is the table name; not the model name
->orderBy('details.name', 'asc')
->get();
If you use this query many times, you could save it in a scope in the Model.
class User extends \Eloquent {
public function scopeUserDetails($query) {
return $query->join('details', 'users.id', '=', 'details.user_id')
}
}
Then call the query from your controller.
$users = User::userDetails()->orderBy('details.name', 'asc')->get();

How to order by another table join by eager loading in Laravel

I got product and stocks table;
products
id int
name varchar
created_at timestamp
stocks
id int
name varchar
product_id varchar
created_at timestamp
Product Model
public function validStock() {
return $this->hasMany('Stock')->where('quantity', '>', 10);
}
If both have created_at, how to order by stocks's created_at, I've tried two methods and it's not work
Product::with('validStock')->orderBy('validStock.created_at', 'DESC');
Product::with(array('validStock' => function($q) {
$q->orderBy('created_at', 'DESC');
}));
Instead of sorting after retrieving all data (which is impossible to do in an efficient way when paginating results) you can use a join.
(This answer is based on this one.)
Product::with('validStock')
->join('stocks', 'stocks.product_id', '=', 'products.id')
->select('products.*') // Avoid selecting everything from the stocks table
->orderBy('stocks.created_at', 'DESC')
->get();
The only thing I don't like about this is that it takes away some of the database abstraction, in that you have to write your table names here.
Note that I haven't tried this with a hasMany relationship in this direction, as you have it in your example (selecting products, and each product has many stocks). I've tried only with the hasMany in the other direction (eg selecting stocks, each of which has exactly one product).
You can not apply an order while querying an eagerly loaded relationship in Laravel. You can order the Collections after the query has been performed.
$products = Product::with(array('validStock'))
->get()
->each(function ($product)
{
$product->validStock = $product->validStock
->sortBy(function ($validStock)
{
return $validStock->created_at;
})
->reverse();
});
You should return $q in the closure:
Product::with(array('validStock' => function($q) {
return $q->orderBy('created_at', 'DESC');
}));

Resources