Display specific column name in laravel 5.6 - laravel

I am using laravel 5.6. I've two tables. One is Teachers(id,name,email,salary) another is Students(id,teacher_id,name,email) I have joined 2 tables
$vu_data = Teacher::join('Students', 'teachers.id', '=', 'students.teacher_id')
->where('teachers.id', $id)
->get();
return view('view_full')->with('vu_data',$vu_data);
view_full.blade.php
{{$vu_data[0]->name}}
How can I display sthdent name and teacher nam. There are same column name.
Thanks in advance

The better way is to use laravel Eloquent relationships https://laravel.com/docs/5.7/eloquent-relationships#one-to-many*.
Put on your Teachers model
public function students(){
return $this->hasMany('App\Students', 'teacher_id', 'id');
}
You will call like that:
$vu_data->students()
If you want to use yur select, simple use de 'AS'
->select('Teachers.name as teacher_name', 'Students.name as student_name')

You'll need to specify the columns in a select() clause on the query, and rename the columns. Such as
Teacher::join('Students', 'teachers.id', '=', 'students.teacher_id')
->where('teachers.id', $id)
->select('teachers.name AS teacher_name', 'students.name AS student_name', [ rest of columns])
->get();
However, you might want to look into Eloquent relationships, which will allow you to iterate through a teacher then all of that teacher's students, or vice versa.

You need to add before ->get()
->select('Teachers.name as teacherName', 'Students.name as studentName')
and than you can use
{{$vu_data[0]->teacherName}}
and
{{$vu_data[0]->studentName}}

As per your table structure one teacher has many students. Hence instead of using join you can use laravel relationships with hasMany :
Teacher has many students - Teacher Model :
public function students(){
return $this->hasMany(Students::class);
}
A student belongs to a teacher - Student Model :
public function teacher(){
return $this->belongsTo(Teacher::class);
}
Now you can get relationships like below :
Get all teachers with their students :
$teachers = Teacher::with('students')->get();
Get all students of a particular techer :
$teacher = Teacher::find($teacherId);
$students = $teacher->students;
Finally using this, you can convert this :
$vu_data = Teacher::join('Students', 'teachers.id', '=', 'students.teacher_id')
->where('teachers.id', $id)
->get();
return view('view_full')->with('vu_data',$vu_data);
To this :
$teacher = Teacher::find($id);
return view('view_full', compact('teacher'));
Then inside blade :
You can get teacher details : {{ $teacher->name }}
and students :
#if($teacher->students->count() > 0)
#foreach($teacher->students as $student)
{{ $student->name }}
#endforech
#endif

Related

Join tables in Laravel Eloquent method

How to write this code in eloquent method ?
$product = DB::table('products')
->join('purchase', 'products.id', '=', 'purchase.id')
->join('sales', 'purchase.id', '=', 'sales.id')
->select('sales.*', 'purchase.*','products.*')
->get();
Create model Product and add one to many relationship with Purchase in Product model.
public function purchases()
{
return $this->hasMany('App\Models\Purchase');
}
Create model Purchase and add one to many relationship with Sale in Purchase model.
public function sales()
{
return $this->hasMany('App\Models\Sale');
}
Create model Sale.
You can retrieve data using following statement.
$products = Product::with('purchases.sales')->get();
Note: I am assuming the relationship as one to many you can also declare as per your data, also you can define one to many inverse relationship, please refer to laravel docs https://laravel.com/docs/8.x/eloquent-relationships#one-to-many.
You will get purchases and sales data in different key so you can use below syntax to loop over it.
foreach ($products as $product) {
foreach ($product->purchases as $purchase) {
//Purchase data for current product
foreach($purchase->sales as $sale){
//Sale data for current purchase
}
}
}

Laravel - Filter records by distinct relation

Right now I have the following models structure,
Country -> State -> City -> Student
And the Student model includes first_name and last_name.
So, I want countries to by filtered by giving student's first name. Like if I give John then I want list of countries which has students whose first name is John.
I was trying something like this,
I added a method called Students() in Country model and returning Student instances from that method. But now I stuck to find out how to filter countries.
Thanks in anticipation.
I came across a similar question recently and I came with the following solution myself. Probably, there are easier ways, but this will get you going for now, I guess.
First we query all the users with first_name == John, as you described, and we limit the query to output only the ID's.
$users = User::where('first_name', 'John')->get()->pluck('id');
We then cross-compare this with the result of Students() from the country model. As I don't know what you're querying for to get the country that you want, I'll just take the Netherlands as an example — that's where I'm from.
$users = Country::where('name', 'the Netherlands')->students()->whereIn('id', $users)->get();
For this to work, you must make sure that within the Students()-function in your model, the get() is left out.
Final 'result':
$users = User::where('first_name', 'John')->get()->pluck('id');
$users = Country::where('name', 'the Netherlands')->students()->whereIn('id', $users)->get();
in the Student Model create this:
public function city()
{
return $this->belongsTo(City::class,'city_id', 'id');
}
and in the City Model create this:
public function state()
{
return $this->belongsTo(State::class,'state_id', 'id');
}
Finally in the State Model:
public function country()
{
return $this->belongsTo(Country::class,'country_id', 'id');
}
For example if you made things like that in controller:
$students = Student::where('name', 'John')->get();
in the view:
#foreach($students as $student)
$student->city->state->country->country_name;
#endforeach
You can access like that.
If you have setup the model and relationship properly then you need to call them using in with function
$students = Student::where('name','John')->with('city.state.country')->get();
Loop through the $students
#foreach($students as $student)
{{ $student->city->state->country }}
#endif

How do i query the database to grab each user post and count the number of post from the user?

I am trying to make a datatable, but I am having trouble querying the database. What I want to do is select one instance of each user on the datatable and I want to grab a count of all the products created by that user.
Products Table
id user_id title
1 2 tv
2 2 car
3 2 book
4 3 glasses
So user(2) has 3 products
So user(3) has 1 products
Here is the code I been working on
$users = DB::table('users')
->join('products', 'users.id', '=', 'products.user_id')
->select('users.*', 'products.id', 'url')
->groupBy('products.id', 'url')
->get();
You need to select the user details, together with a count of the products, grouped by the user id, as follows:
$users = DB::table('users')
->selectRaw('users.*, COUNT(products.id) AS products')
->join('products', 'users.id', '=', 'products.user_id')
->groupBy('users.id')
->get();
You can do this really simply with eloquent
Say you have your User model and Product model.
In your database structure, for your products table, you need to include a column called user_id as an integer data type.
Then You declare this relationship on the user model
public function products()
{
return $this->hasMany(Product::class);
}
then the inverse of the relation on the product's model
public function user()
{
return $this->belongsTo(User::class);
}
Now you can simply do the following
//This returns all users with products (eager loading pointes out by fubar)
$users = User::with('products')->get();
//Now you could pass $users to your view and loop through like so
#foreach($users as $user)
<li>{{ $user->name }} has {{ $user->products->count() }} </li>
#endforeach
for a specific user, you can simply
$user = User::find($id);
$userProductCount = $user->products->count();
eloquent really does make everything so clean and beautiful

Scope query in a many to many relationship

I created 2 models, "Post" and "Category". This is a many to many relationship, works great.
My tables are the following :
alex_blog_posts : where posts are stored with columns like "title", "published" etc...
alex_blog_categories : where categories are stored with columns like "title", "parent_id" etc...
alex_blog_posts_categories : where the relation is stored between posts and categories with columns "post_id", "category_id"
Let's assume I want to filter all posts that are associated to a category with name : "Category 1"
public function scopeFilterCategory($query) {
$query->join(????); // My problem is to replace the ???
$query->where('title', '=', 'Category 1');
return $query;
}
I'm not familiar enought with october and laravel yet and I'm stuck here. Probably very simple for laravel expert but I need a concrete example of something working cause all things I tried failed :/
Thanks for your help
laravel have the "whereHas":
https://laravel.com/docs/5.5/eloquent-relationships#querying-relationship-existence
On the post model you need the write this query:
$posts = Post::whereHas($relationName, function ($query) {
$query->where('title', =, 'Category 1');
})->get();
$relationName - should be the name of the function that define the relation in your model (etc: 'categories')
For Laravel
There is a good answer on Laracasts
Scope for many to many relation
The following is an improved version.
Assume we have authors & articles many-to-many relation (with a pivot authors_articles);
Assume we have belongsToMany relation defined in both models;
// in Article model
public function scopeFromAuthor($query, $authorId)
{
return $query->whereHas('authors', function ($query) use ($authorId) {
$query->where('authors_articles.author_id', '$authorId');
});
}

Laravel Eloquent complex join statement

My database structure is the following:
So I've got a Bloggers table (sorry for the typo in the image), which has 3 topic fields, all 3 are foreign keys to the topics' table id.
I made a Blogger view front-end with a simple table showing all blogger columns. At the moment, the id's of the topics are being shown instead of the names though.
How can I change this?
I've already tried the following in my Controller, but that just creates duplicates in the view with different values in the main_topic column.
$bloggers= DB::table('bloggers')
->join('topics', function ($join) {
$join
->on('bloggers.main_topic', '=', 'topics.id')
->orOn('bloggers.subtopic1', '=', 'topics.id')
->orOn('bloggers.subtopic2', '=', 'topics.id');
})
->select('bloggers.*', 'topics.name as main_topic')
->get();
return view('pages.bloggers', compact('bloggers'));
The answer to my specific question was a little different from the answers given, so I'll post it here in case anyone needs it in the future.
So I've got 3 tables: bloggers, topics and a pivot table called blogger_topic. bloggers contains 3 foreign keys (integers) to topics called main_topic, subtopic1, subtopic2. The pivot table contains a blogger_id, and a topic_id.
What I ended up with:
Blogger.php model:
public function mainTopic()
{
return $this->belongsTo('App\Models\Topic', 'main_topic', 'id');
}
public function subtopicOne()
{
return $this->belongsTo('App\Models\Topic', 'subtopic1', 'id');
}
public function subtopicTwo()
{
return $this->belongsTo('App\Models\Topic', 'subtopic2', 'id');
}
Topic.php model:
public function bloggers()
{
return $this->belongsToMany('App\Models\Blogger');
}
View (blogger.blade.php):
#foreach($bloggers as $blogger)
{{ $blogger->mainTopic }}
{{ $blogger->subtopicOne }}
{{ $blogger->subtopicTwo }}
#endforeach
I think you should change your database tables if possible as below (sample link), by creating a pivot table. And then I think you should make relationships in Blogger and Topic model files with many-to-many. Then it would be very easy to fetch all related topics. For eg,
$topics = $blogger->topics;
Here you can reference the sample db table designs
I kindly recommend you to use models in Laravel coz they'll make your life more simple. Hope this help.
If you cant change your database, you could use group_concat on the results. Not sure if it will work but something like:
DB::table('bloggers')
->join('topics', function ($join) {
$join
->on('bloggers.main_topic', '=', 'topics.id')
->orOn('bloggers.subtopic1', '=', 'topics.id')
->orOn('bloggers.subtopic2', '=', 'topics.id');
})
->groupby('bloggers.id')
->select('bloggers.*', 'topics.name as main_topic', DB::raw('group_concat(topics.name)'))
->get();

Resources