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');
Related
I have following tables
Messages:
user_id
group_id
text
created_at
And
group_users:
user_id
left_at
group_id
These tables have relationship via "group_id".
I need "Messages" that created before "group_user" left group.
In other word, i need a query like this:
$messages = Message::where('created_at','<',group_user.left_at)->get();
How can i achieve this?
You can simply do it like this assuming you have the user ID at hand:
Message::join('group_users', 'messages.group_id', '=', 'group_users.group_id')
->where('group_users.user_id', $id)
->where('group_users.left_at', '>', 'messages.created_at')
->get();
it can be like the code below(untested):
in the Message model
public function group(){
return $this->belongsTo(Group::class);
}
in the controller
$messages = Message::whereHas('group', function($q){
$q->where('left_at','>','messages.created_at');
})->get();
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.
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'));
}
My target is to get collection of books with count of matches book.names in another table without relation
I get collection like this
$books = Books::paginate(20);
What I need now is to get the count of matches like this
SELECT COUNT(*) FROM `posts` WHERE `body` LIKE '%book.name%'
How can I do this with one query and avoiding unnecessary queries for each model, like eager loading
You can do it with eager loading without loading all post. There is a method called withCount
Books.php
public function posts() {
return $this->hasMany(Post::class, 'post_id', 'id');
}
One way to find all post related to book is
$books = Books::withCount(['posts' => function ($query) use($searchTerm) {
$query->where('body', 'like', $searchTerm);
}])->get();
//How to retrieve
$book = $books->first()->posts_count.
You can find more information about withCount on laravel documentation website.
Approach 2: Without Eager Loading
$books = Books::select('*')->addSelect(DB::raw("SELECT COUNT(*) as post_count FROM `posts` WHERE `body` LIKE '%book.name%' ")->get(); //This will return collection with post_count.
Note: Not tested
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();