Fundamental misunderstanding of model in Eloquent (Outside of Laravel)
My previous question that ceejayoz helped point me in the right direction for, but that has led me to what is basically a new question.
I'm working on a simple chemical tracking database and have it structured with a chemicals table which tracks most of the info but I have a few fields that started out as Enums but I realized that would not work for. There are now separate tables for company, room, and location. All of these additional tables include just an id and the field so company is:
1 | 'FISHER'
2 | 'BDH'
etc.
I can do
$company = chemical::find(4)->company;
for example and that will give me the name of the company for that chemical, but what I am trying to do is display a table with all of the information in each chemical, as well as the associated company name, room, location.
I am just not sure as to how to accomplish this.
How would I even get the associated company for all the chemicals?
$chemicals = company::all()->company;
Does not work and I can see why.
$chemicals = chemical::all();
foreach($chemicals as $chem) {
echo $chem->company . "<br />";
}
Will get me the associated companies and that's great, but then where do I go from there in terms of the comprehensive table?
You don't specify how your tables company
, room
, and location
are related to chemicals
. However, if they are all belongsTo
type relationships, then I believe you are looking for Eager Loading:
Eloquent can "eager load" relationships at the time you query the parent model. Eager loading alleviates the N + 1 query problem.
To eager-load multiple relationships, you can do something like:
$chemicals = chemical::with('company', 'room', 'location')->get();
If you are using a templating engine like Twig or Blade (which hopefully you are), you can then pass your $chemicals
directly to the template. Otherwise, you can iterate through $chemicals
as you demonstrated in your question:
echo "<table><thead><tr>
<th>Chemical ID</th>
<th>Chemical Name</th>
<th>Company Name</th>
<th>Location Name</th>
<th>Room Name</th>
</tr></thead><tbody>";
foreach($chemicals as $chem) {
echo "<tr><td>{$chem->id}</td>
<td>{$chem->name}</td>
<td>{$chem->company->name}</td>
<td>{$chem->location->name}</td>
<td>{$chem->room->name}</td>
</tr>";
}
echo "</tbody></table>";
Please also notice that the convention in Eloquent is to capitalize your model class names (Chemicals
, not chemicals
).
The question is a little unclear, but for a table of chemicals that includes their company data, you'd do something along these lines. In your controller:
// we use with() to "eager load" the company data
// this makes the following line execute two queries
// without the with(), our Blade template will make a query
// to the companies table for EVERY row in the table
// if you have hundreds/thousands of chemicals, you'll
// want to consider paginate() instead of get() too
$chemicals = Chemical::with('company')->get();
return view('your.view')->withChemicals($chemicals);
In your Blade view, you can access all of each chemical's company's properties:
<table>
@foreach($chemicals as $chemical)
<tr>
<td>{{ $chemical->name }}</td>
<td>{{ $chemical->company->name }}</td>
</tr>
@endforeach
</table>
I guess, what you asked for, is this:
chemicals: id, company (ENUM), ...
now you extracted data to
companies: id, name (same as ENUM in chemicals previously)
If that's the case, then you can do 2 things:
create ordinary relationship with id
and company_id
beings the keys and update your chemicals
table to add appropriate company_id
values depending on their company
enum/string value, then drop company
column. It may require more adjustments, eg. everywhere where you called chemical->company
to get the company name (becomes chemical->company->name
)
create a relationship based on the chemicals.company
and companies.name
fields.
Definitely the first option is better in the long run.