Understanding the Show Method for Data Display
The last article ended with us showing all of the resources in the personal_cars
table. We need to be able to click on the resource and pull up the details for it. This is what the show
method will do. It accepts a resource $id
and then pulls the information from it.
Adding the Link to Our Index View
Before we can start working on the show
method, we need to have a way to get to it. The route exists, so that’s one thing already cross off the list.
Route::prefix('/personalcars')->group(function() {
// ...
Route::get('/{id}', [PersonalCarController::class, 'show']);
});
The user simply needs to type in localhost/personalcars/1
to get the first resource. Let’s add the links to our resources/views/personalcars/index
file. I’ll add one more column at the end to create our link.
<x-layouts.app title="{{ $title }}">
<div class="flex bg-white mt-12" style="height:600px;">
<div class="items-center text-center lg:text-left px-8 md:px-12 lg:w-full">
<div class="relative overflow-x-auto">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">
Year
</th>
<th scope="col" class="px-6 py-3">
Make
</th>
<th scope="col" class="px-6 py-3">
Model
</th>
<th scope="col" class="px-6 py-3">
Exterior Color
</th>
<th scope="col" class="px-6 py-3">
Current Value
</th>
<th scope="col" class="px-6 py-3">
View
</th>
</tr>
</thead>
<tbody>
@foreach($cars as $car)
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
<th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
{{ $car->year }}
</th>
<td class="px-6 py-4">
{{ $car->brand->name }}
</td>
<td class="px-6 py-4">
{{ $car->model->name }}
</td>
<td class="px-6 py-4">
{{ $car->exterior_color }}
</td>
<td class="px-6 py-4">
{{ $car->current_value }}
</td>
<td class="px-6 py-4">
<a href="/personalcars/{{ $car->id }}">
Show Car
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</x-layouts.app>
If we just isolate that column, we see:
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<!-- ... -->
<th scope="col" class="px-6 py-3">
View
</th>
</tr>
</thead>
<tbody>
@foreach($cars as $car)
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
<!-- ... -->
<td class="px-6 py-4">
<a href="/personalcars/{{ $car->id }}">
Show Car
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
Now, when we click on the Show Car
link, we get directed to our show
method.
Show Method
Data is being passed from our link to the route and to our show
method in our controller. We simply need to pull the data now and place it into a view.
<?php
namespace App\Http\Controllers;
use App\Models\PersonalCar;
use Illuminate\Http\Request;
class PersonalCarController extends Controller
{
// ...
/**
* Display the specified resource.
*
* @param int $id
*/
public function show($id)
{
$car = PersonalCar::with(['brand', 'model', 'images'])->find($id);
dd($car);
// Send data to show view
// Return view to user through route
}
}
If we click on any of those links, we should get the data for the car.
We simply now need to pass that data to a view and display it.
public function show($id)
{
$car = PersonalCar::with(['brand', 'model', 'images'])->find($id);
return view('personalcars/show', [
'title' => $car->year . " " . $car->brand->name . " " . $car->model->name,
'car' => $car,
]);
}
The view needs to display all of the data and loop through all of the images. I updated some images in the database table so that actual images pull up.
mysql> update images set url = "https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG18.png" where id = "1";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update images set url = "https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG23.png" where id = "2";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update images set url = "https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG25.png" where id = "3";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update images set url = "https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG60.png" where id = "4";
Query OK, 1 rows affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from images;
+----+---------------------------------------------------------------+---------------------+---------------------+---------------------+
| id | url | alt | created_at | updated_at |
+----+---------------------------------------------------------------+---------------------+---------------------+---------------------+
| 1 | https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG18.png | 2007 Chevy Corvette | 2023-01-22 13:15:11 | 2023-01-22 13:15:11 |
| 2 | https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG23.png | 2003 Chevy Corvette | 2023-01-22 13:29:50 | 2023-01-22 13:29:50 |
| 3 | https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG25.png | 2003 Chevy Corvette | 2023-01-22 13:30:08 | 2023-01-22 13:30:08 |
| 4 | https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG60.png | Test Image | 2023-01-22 13:36:52 | 2023-01-22 13:36:52 |
+----+---------------------------------------------------------------+---------------------+---------------------+---------------------+
4 rows in set (0.00 sec)
A new file, called resources/views/personalcars/show.blade.php
was created. The file displays all of the regular data and all of the images.
<x-layouts.app title="{{ $title }}">
<div class="flex bg-white mt-12" style="height:600px;">
<div class="w-full max-w-6xl rounded bg-white shadow-xl p-10 lg:p-20 mx-auto text-gray-800 relative md:text-left">
<div class="md:flex items-center -mx-10">
<div class="w-full md:w-1/2 px-10 mb-10 md:mb-0">
<div class="relative">
<img src="https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG16.png" class="w-full relative z-10" alt="">
<div class="border-4 border-blue-200 absolute top-10 bottom-10 left-10 right-10 z-0"></div>
</div>
</div>
<div class="w-full md:w-1/2 px-10">
<div class="mb-10">
<h1 class="font-bold uppercase text-2xl mb-5">{{ $car->year . " " . $car->brand->name . " " . $car->model->name }}</h1>
<ul class="text-sm">
<li>Year: {{ $car->year }}</li>
<li>Make: {{ $car->brand->name }}</li>
<li>Make: {{ $car->model->name }}</li>
<li>Transmission: {{ $car->is_manual ? "Manual" : "Automatic" }}</li>
<li>Purchase Amount: {{ $car->purchase_amount }}</li>
<li>Current Value: {{ $car->current_value }}</li>
<li>Sales Amount: {{ $car->sales_amount == 0 ? "N/A" : $car->sales_amount }}</li>
<li>Date Purchased: {{ $car->date_purchased }}</li>
<li>Date Sold: {{ $car->date_sold == null ? "N/A" : $car->date_sold }}</li>
</ul>
</div>
<div>
<div class="inline-block align-bottom mr-5">
<span class="font-bold text-5xl leading-none align-baseline">{{ $car->current_value }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex w-full flex-wrap content-center justify-center p-10">
<div class="grid grid-cols-4 gap-3">
@foreach( $car->images as $image )
<div class="w-80 bg-white p-3">
<img class="h-52 w-full object-cover" src="{{ $image->url }}" alt="{{ $image->alt }}" />
</div>
@endforeach
</div>
</div>
</x-layouts.app>
When we refresh the page, we get to see this beauty.
The logic is nearly identical to our index
method so we won’t go too far into it.
There is one issue that I’m seeing though. The purchase amount is displaying in pennies. Technically the sales amount would also display as pennies if it was larger than 0.
To fix it, we need to create a new function, identical to our current_value
getter, and the problem will be fixed.
Open your PersonalCar
model and add two new methods:
purchaseAmount
forpurchase_amount
salesAmount
forsales_amount
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class PersonalCar extends Model
{
// ...
protected function currentValue(): Attribute
{
return Attribute::make(
get: fn($value) => "$" . number_format($value / 100, 2, '.', ','),
);
}
protected function purchaseAmount(): Attribute
{
return Attribute::make(
get: fn($value) => "$" . number_format($value / 100, 2, '.', ','),
);
}
protected function salesAmount(): Attribute
{
return Attribute::make(
get: fn($value) => "$" . number_format($value / 100, 2, '.', ','),
);
}
}
For the sales amount, we do want to see the “N/A” and not $0.00. We can modify that in the show.blade.php
file or we could move the logic back to our model if we’re confident that “N/A” should always be displayed if the sales amount is 0.
protected function salesAmount(): Attribute
{
return Attribute::make(
get: fn($value) => ($value == 0 ? "N/A" : "$" . number_format($value / 100, 2, '.', ',')),
);
}
We can add two more methods to our model:
isManual
foris_manual
dateSold
fordate_sold
We would do this to remove the logic from our show.blade.php
file.
<li>Transmission: {{ $car->is_manual ? "Manual" : "Automatic" }}</li>
<li>Date Sold: {{ $car->date_sold == null ? "N/A" : $car->date_sold }}</li>
protected function isManual(): Attribute
{
return Attribute::make(
get: fn($value) => ($value == 1 ? "Manual" : "Automatic"),
);
}
protected function dateSold(): Attribute
{
return Attribute::make(
get: fn($value) => ($value == null ? "N/A" : $value),
);
}
Our show view can now be nice and simple.
<div class="mb-10">
<h1 class="font-bold uppercase text-2xl mb-5">{{ $car->year . " " . $car->brand->name . " " . $car->model->name }}</h1>
<ul class="text-sm">
<li>Year: {{ $car->year }}</li>
<li>Make: {{ $car->brand->name }}</li>
<li>Make: {{ $car->model->name }}</li>
<li>Transmission: {{ $car->is_manual }}</li>
<li>Purchase Amount: {{ $car->purchase_amount }}</li>
<li>Current Value: {{ $car->current_value }}</li>
<li>Sales Amount: {{ $car->sales_amount }}</li>
<li>Date Purchased: {{ $car->date_purchased }}</li>
<li>Date Sold: {{ $car->date_sold }}</li>
</ul>
</div>
That’s it. We have a fully functional show
page. The full code for it is as follows:
show.blade.php
view
<x-layouts.app title="{{ $title }}">
<div class="flex bg-white mt-12" style="height:600px;">
<div class="w-full max-w-6xl rounded bg-white shadow-xl p-10 lg:p-20 mx-auto text-gray-800 relative md:text-left">
<div class="md:flex items-center -mx-10">
<div class="w-full md:w-1/2 px-10 mb-10 md:mb-0">
<div class="relative">
<img src="https://pngimg.com/uploads/chevrolet/%D1%81hevrolet_PNG16.png" class="w-full relative z-10" alt="">
<div class="border-4 border-blue-200 absolute top-10 bottom-10 left-10 right-10 z-0"></div>
</div>
</div>
<div class="w-full md:w-1/2 px-10">
<div class="mb-10">
<h1 class="font-bold uppercase text-2xl mb-5">{{ $car->year . " " . $car->brand->name . " " . $car->model->name }}</h1>
<ul class="text-sm">
<li>Year: {{ $car->year }}</li>
<li>Make: {{ $car->brand->name }}</li>
<li>Make: {{ $car->model->name }}</li>
<li>Transmission: {{ $car->is_manual }}</li>
<li>Purchase Amount: {{ $car->purchase_amount }}</li>
<li>Current Value: {{ $car->current_value }}</li>
<li>Sales Amount: {{ $car->sales_amount }}</li>
<li>Date Purchased: {{ $car->date_purchased }}</li>
<li>Date Sold: {{ $car->date_sold }}</li>
</ul>
</div>
<div>
<div class="inline-block align-bottom mr-5">
<span class="font-bold text-5xl leading-none align-baseline">{{ $car->current_value }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex w-full flex-wrap content-center justify-center p-10">
<div class="grid grid-cols-4 gap-3">
@foreach( $car->images as $image )
<div class="w-80 bg-white p-3">
<img class="h-52 w-full object-cover" src="{{ $image->url }}" alt="{{ $image->alt }}" />
</div>
@endforeach
</div>
</div>
</x-layouts.app>
PersonalCar
model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class PersonalCar extends Model
{
use HasFactory;
protected $fillable = [
'year', 'is_manual', 'exterior_color', 'purchase_amount', 'current_value', 'sales_amount', 'date_purchased', 'date_sold'
];
public function brand()
{
return $this->belongsTo(PersonalCarBrand::class, 'personal_car_brand_id', 'id');
}
public function model()
{
return $this->belongsTo(PersonalCarModel::class, 'personal_car_model_id', 'id');
}
public function images()
{
return $this->belongsToMany(Image::class);
}
protected function currentValue(): Attribute
{
return Attribute::make(
get: fn($value) => "$" . number_format($value / 100, 2, '.', ','),
);
}
protected function purchaseAmount(): Attribute
{
return Attribute::make(
get: fn($value) => "$" . number_format($value / 100, 2, '.', ','),
);
}
protected function salesAmount(): Attribute
{
return Attribute::make(
get: fn($value) => ($value == 0 ? "N/A" : "$" . number_format($value / 100, 2, '.', ',')),
);
}
protected function isManual(): Attribute
{
return Attribute::make(
get: fn($value) => ($value == 1 ? "Manual" : "Automatic"),
);
}
protected function dateSold(): Attribute
{
return Attribute::make(
get: fn($value) => ($value == null ? "N/A" : $value),
);
}
}
PersonalCarController
<?php
namespace App\Http\Controllers;
use App\Models\PersonalCar;
use Illuminate\Http\Request;
class PersonalCarController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$cars = PersonalCar::with(['brand', 'model'])->orderBy('year', 'desc')->get();
return view('personalcars/index', [
'title' => 'Personal Cars',
'cars' => $cars,
]);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
// Return the form to the user
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// get data from form
// validate data
// insert data into table
// return message that insertion was successful
}
/**
* Display the specified resource.
*
* @param int $id
*/
public function show($id)
{
$car = PersonalCar::with(['brand', 'model', 'images'])->find($id);
return view('personalcars/show', [
'title' => $car->year . " " . $car->brand->name . " " . $car->model->name,
'car' => $car,
]);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
// get resource with the help of the PersonalCar model
// send data to edit view
// the view injects the data into the form
// the view is returned to the user through the route
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
// get data from form
// update the resource with the form data
// return a success message
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
// delete the record from the table
// return redirect with success message
}
}
Next time we’ll tackle inserting a new car into the database.
Laravel Series
Continue your Laravel Learning.
Laravel Index Method: A Guide to Controller Essentials
Laravel – P40: CMP – Controller Index
Explore the role of the Index Method in Laravel controllers. Learn how to effectively utilize this method to manage and display data in your application.
Understanding the Show Method for Data Display
Laravel – P41: CMP – Controller Show
Learn how to use Laravel’s Show Method in controllers to effectively display individual data records. A comprehensive guide for streamlining your app.
Controller Essentials: Understanding Laravel’s Create/Store Methods
Laravel – P42: CMP – Insert Data
Explore Laravel’s Create/Store methods in controllers for seamless data creation and storage. A guide to efficiently handling form submissions in Laravel.