I'm trying to display authors.where some books have one author and some books have 2 authors. How to manipulate this scenario
here is my html code
#foreach($books as $book)
<tr>
#if (json_encode($book['author']) !== 1 )
<td>{{{ json_decode(json_encode($book['author'][0]),true) }}} &
{{{ json_decode(json_encode($book['author'][1]),true) }}}</td>
#else
<td>{{{ $book['author'][0] }}}</td>
#endif
</tr>
But It is displaying only 2 authors but not single author.Any help or suggestions that would be appericated
Thanks In advance
I don't know how you have your tables setup but if authors are on a separate table as they should with a hasMany relation you should do this(assuming your relations are well formed)
Book Model, you described a One to Many relation between Books and Authors so you should use something like this:
public function authors()
{
return $this->hasMany('App\Author');
}
#foreach ($books as $book) :
#foreach($book->authors as $author) :
// do whatever you wish with all the authors here
#endforeach
#endforeach
Related
I have 2 tables in my db, 1 for Collabs and 1 for Projects
I want when I view a project, to display the collabs based on that project (if i press view on a project for example project with id = 10, to display all Collabs for the project that is id 10).
For Collabs table I have id_project that is wanted to be in relationship with id from Project table, so when I insert a new collab in my Collabs table it takes the id from the project I inserted.
For now, this is how I display the collabs, and i display them all for all projects but I don't want that.
#forelse ($istoric as $istProj)
<div class="mb-3">
<table class='table'>
<tr class="table-row-heads">
<th>Id Proiect</th>
<th>Tip actiune </th>
<th>Colaborator </th>
<th>Suma </th>
<th>Data </th>
</tr>
<tr class="table-row-data">
<td>{{ $istProj->id_proiect }}</td>
<td>{{ $istProj->action_type }}</td>
<td>{{ $istProj->colaborator_id }}</td>
<td>{{ $istProj->suma }}</td>
<td>{{ $istProj->data }}</td>
</tr>
</table>
</div>
#empty
<div class="card-body">
<h2>Nu au fost gasite inregistrari</h2>
</div>
#endforelse
You should really consider reading and watching more videos on how relationships and eloquent works, I hope this below is a good reference for you to get started, please read carefully, and sorry I couldn't translate back to romanian, and to avoid any mistakes, I kept my code in english.
Caloboratori = Colaborators
Istoric Proiecte = Project History
id || auto_increment
project_id || bigInteger()
colaborator_id || bigInteger()
Proiecte = Project
id || auto_increment
Project Model
/* To load the history, we will be using hasMany relationship, because for each
project, we have lots of history, please read more on one-to-many relationships here
https://laravel.com/docs/9.x/eloquent-relationships#one-to-many
Istoric Proiecte = Project History
id || auto_increment
project_id || bigInteger()
colaborator_id || bigInteger()
*/
public function histories() {
return $this->hasMany(ProjectHistory::class);
}
Project History Model
//We will reverse the one-to-many relationship, with belongsTo here. | example: project_id
public function project() {
return $this->belongsTo(Project::class);
}
//We will reverse the one-to-many relationship, with belongsTo here. | example: colaborator_id
public function colaborator() {
return $this->belongsTo(Colaborator::class);
}
Projects Controller:
// Show a list of all projects
public function index() {
//Get all projects
$projects = Project::all();
//Load all of the project relationships that we will be using
$projects->load('histories.colaborator');
return view('projects.index', compact('projects'));
}
// Show a single project
public function show(Project $project) {
//Load all of the project relationships that we will be using
$project->load('histories.colaborator');
//Assign the loaded project history
$histories = $project->histories;
return view('projects.show', compact('project', 'histories'));
}
projects.index Blade: in this blade, you can forloop thru all of your projects model, and assign them as $project, since we loaded the relationships earlier from the controller.
You can easily access the relationships using $project->histories then assign each history model to $history.
Then you can go one step inside of the history relationship and call the inner relationship of colaborator with $history->colaborator
#foreach ($projects as $project)
<p>Project id: {{ $project->id }}
<p>Project name: {{ $project->name }}
<h1>Project History list</h1>
#foreach ($project->histories as $history)
<ul>
<li>ID: {{$history->id}}</li>
<li>Name: {{$history->name}}</li>
<li>Colaborator Name: {{$history->colaborator->name}}</li>
</ul>
#endforeach
#endforeach
projects.show Blade: in this blade, we have a single project, and you can forloop thru all of your history models, since we loaded the relationships from the controller.
We assigned the histories collection as $histories then assign each history model to $history
Then you can go one step inside the history relationship and call the inner relationship of colaborator with $history->colaborator
<p>Project name: {{ $project->name }}
<h1>Project History list</h1>
#foreach ($histories as $history)
<ul>
<li>ID: {{$history->id}}</li>
<li>Name: {{$history->name}}</li>
<li>Colaborator Name: {{$history->colaborator->name}}</li>
</ul>
#endforeach
If you use model Collab, and within you have project relation , than you can use
Collab::query()
->with('project', function ($q) use ($id) {
return $q->where('id', $id);
})
->get();
Or you can use query builder as well
DB::table('collabs')
->select('collabs.*')
->join('projects', 'projects.id', '=', 'collabs.project_id')
->where('projects.id', $id)
->get();
Just adjust it according what you really need.
Let's say I have 250 users in users table and each user has one or many books, and each book has one or many chapters. Now I would like to print the user names, with their book names.
Controller:
$users = User::all();
in blade:
#foreach($users as $user)
<tr>
<td>{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>
#foreach($user->books as $book)
{{ $book->name }},
#endforeach
</td>
</tr>
#endforeach
# of queries 252
Now to overcome the n+1 problem, the query should be
$users = User::with('books')->get();
Now the # of queries are only 2.
I want to print the book names with number of chapters like this->
BookName(# of chapters). So in my blade
#foreach($users as $user)
<tr>
<td>{{ $user->id }}</td>
<td>{{ $user->name }}</td>
<td>
#foreach($user->books as $book)
{{ $book->name }} ({{ $book->chapters->count() }}),
#endforeach
</td>
</tr>
#endforeach
so for 750 books with 1500 chapters the # of queries are about 752 and it increases if chapter number increases.
Is there any better Eloquent way to reduce it or should I go for raw SQL queries?
You don't need to load all chapters data and then manually count each collection. Use withCount() instead:
$users = User::with('books')->withCount('chapters')->get();
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models.
From the Eloquent Documentation:
Nested Eager Loading
To eager load nested relationships, you may use "dot" syntax. For example, let's eager load all of the book's authors and all of the author's personal contacts in one Eloquent statement:
$books = App\Book::with('author.contacts')->get();
In your case, you can retrieve the nested relationships you need with the following:
User::with('books.chapters')->get();
First time to try laravel eloquent relatioinstip
I know it's really simple but I am getting this error don't know what's wrong with it
I have 2 tables in data base, news and news_image
in database
Tables:
news
id | header | details
news_image
id | image | news_id
And have 2 models News , newsImage
newsImage model :
class newsImage extends Eloquant {
protected $table = 'news_image';
public function news()
{
return $this->belongsTo('News');
}
}
News model
class News extends Eloquent
{
protected $table = 'news';
public $timestamps = false;
public function image()
{
return $this->hasMany('newsImage');
}
}
The view:
foreach($news as $new)
<tr>
<td> {{$new->id}} </td>
<td> {{ $new->header}}</td>
<td> {{ $new->details }}</td>
</td> {{$new->news->image}}</td>
</tr>
when I run this it's get error :
Trying to get property of non-object (View: /var/www/html/clinics/app/views/news/index.blade.php)
Any ideas on what could be causing this error?
First, assuming what you are passing to your view is an array or Collection of News objects, you should probably be using $new->image to access the News Item relation. By defining the function image() in your News model, you can access the relation with either the ->image or ->image() calls. In either case, what you need to call is probably
$new->image->first()->image
To break that down:
->image gets the Collection of NewsImage relations
->first() gets the first item in the Collection
->image (the secone one) gets the image field from that NewsImage
If the Collection has more than one item, you can instead loop over it to get all of the images as shown in the other answer.
There are a couple things I would change:
In your News model, change the relationship from "image" to "images" since it's a one to many relationship. It just keeps your code clean.
Your foreach loop in your view should loop through all the news models, but remember that each news model has multiple images, so you should have another loop inside your existing loop to display the images, i.e. foreach ($new->images as $image)
#foreach ($news as $new)
<tr>
<td> {{$new->id}} </td>
<td> {{ $new->header}}</td>
<td> {{ $new->details }}</td>
<td>
#foreach ($new->images as $image)
{{ $image->image }}
#endforeach
</td>
</tr>
#endforeach
I'm using the following query to get all companies for a certain event. And they are ordered by name
$companies = Company::where('city_id', 3)->orderBy('name', 'asc')->get();
Now in my view i use eager loading to get all the persons that work for that company
#foreach($companies as $company)
#foreach($company->persons as $person)
<tr><td>{{ $person->firstname }}</td></tr>
#endforeach
#endforeach
I'm trying to sort the persons by name but it's not working. Any idea on how to do this?
Thanks
You can further query your relations in Laravel.
For example to get person by names in an ascending order.
#foreach($companies as $company)
#foreach($company->persons()->orderBy('firstname','asc')->get() as $person)
<tr><td>{{ $person->firstname }}</td></tr>
#endforeach
#endforeach
I am creating a website in Laravel. I currently have two tables: users and cities.
In my models I have linked the both tables as following:
//User.php
public function city()
{
return $this->belongsTo('City', 'id', 'city_id');
}
//City.php
public function users()
{
return $this->hasMany('User');
}
But when I try to get the name of the city the user lives in I get an error. I use the following code to list all users:
<?php $i=0 ?>
#foreach ($users as $user)
<tr>
<td>{{{ ++$i }}}</td>
<td>{{{ $user->firstname }}} {{{ $user->name }}}</td>
<td>{{{ $user->city()->name }}}</td>
</tr>
#endforeach
When I run it, this is the error I get on the line where I try to access $user->city()->name:
ErrorException
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$name (View: /var/www/kljwaregem_2014/app/views/leden/simplelist.blade.php)
I have no idea what I am doing wrong, I followed all the steps in the documentation. Can someone help me with this?
To define the inverse of a OneToMany relationship, use belongsTo and not hasOne, as explained in the documentation.