Laravel — P41: Controller Show Method (CMP)

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 for purchase_amount
  • salesAmount for sales_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 for is_manual
  • dateSold for date_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 — P40- Controller Index Method (CMP)

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.

Laravel — P41: Controller Show Method (CMP)

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.

Laravel — P42: Controller Create/Store (CMP)

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.

Leave a Reply