Home > Software design >  Grab manufacturer logo by 'id' or 'name' and display in table - Laravel 8 - aJax
Grab manufacturer logo by 'id' or 'name' and display in table - Laravel 8 - aJax

Time:05-24

Morning all.

I have created a vehicle database with somewhat detailed information like engine type, fuel, transmission, manufacturer and so on...

I started out by selecting the logo for each entry and soon realized that I will end up with a folder full of the same logos just named differently by timestamp.

I am therefore trying to create a process of manually uploading all the manufacturer logos into an assets folder then when I input the 'Manufacturer Name' it will use the information to pull the relevant logo from public/storage/assets.

My Vehicle Model

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Vehicle extends Model
{
    use HasFactory; /**  Name of columns fillable */
    protected $table = 'vehicles';
    protected $fillable = [
        'make',
        'model_name',
        'version',
        'powertrain',
        'trans',
        'fuel',
        'model_year',
        'image',
        'created_at'

    ];
};

My VehiclesController

namespace App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Models\Vehicle;
use Illuminate\Http\Controllers;
use Illuminate\Database\Migrations\CreateVehiclesTable;

class VehiclesController extends Controller
{
    public function index()
    {
        return view('index');
    }

    /** Handle insert */

    public function store(Request $request)
    {
        // print_r($_POST);
        // print_r($_FILES);
        // // }


        $file = $request->file('image');
        $filename = time(). '.' .$file->getClientOriginalExtension();
        $file->storeAs('public/images', $filename);



        // handle insert vehicle ajax request
        $vehicle = Vehicle::create(
            [
            'make' => $request->make,
            'model_name' => $request->model_name,
            'version' => $request->version,
            'powertrain' => $request->powertrain,
            'trans' => $request->trans,
            'fuel' => $request->fuel,
            'model_year' => $request->model_year,
            'image' => $filename
            ]
        );

        return response()->json($vehicle);
    }

    // FETCH ALL AJAX REQUEST

    public function fetchAll()
    {
        $vehicles = Vehicle::all(); //Could be model or controller...
        $output = '';
        if ($vehicles->count() > 0) {
            $output .= '<table  >
                <thead>
                    <tr>
                        <th >ID</th>
                        <th >Image</th>
                        <th >Make</th>
                        <th >Model</th>
                        <th >Derivative</th>
                        <th >Powertrain</th>
                        <th >Transmission</th>
                        <th >Fuel Type</th>
                        <th >Model Year</th>
                    </tr>
                </thead>
                <tbody>';
            foreach ($vehicles as $vehicle) {
                $output .= '<tr >
                    <td>'.$vehicle->id.'</td>
                    <td><img src="./storage/images/'.$vehicle->image.'"  ></td>
                    <td>'.$vehicle->make.'</td>
                    <td>'.$vehicle->model_name.'</td>
                    <td>'.$vehicle->version.'</td>
                    <td>'.$vehicle->powertrain.'</td>
                    <td>'.$vehicle->trans.'</td>
                    <td>'.$vehicle->fuel.'</td>
                    <td>'.$vehicle->model_year.'</td>
                    <td>
                        <a href="#" id="'.$vehicle->id.'"  data-bs-toggle="modal" data-bs-target="editVehicleModal"><i ></i></a>

                        <a href="#" id="'.$vehicle->id.'" ><i class-"bi-trash h4"></i></a>
                    </td>
                </tr>';
            }
            $output .= '</tbody></table>';
            echo $output;
        } else {
            echo '<h1 >No vehicles in the database!</h1>';
        }
    }

    public function time($time)
    {
        $time->Carbon::now();
    }
}

My Migration file

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateManufacturersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('manufacturers', function (Blueprint $table) {
            $table->id('id');
            $table->string('manu_logo');
            $table->string('manu_name');
            $table->timestamps('created_at');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('manufacturers');
    }
}

I am under the impression that I will need to generate a new model and use the present VehiclesController to pull the logo from the manufacturers model.

I think I'm getting a little confused and would appreciate any help, if anymore information is needed please dont hesitate to ask

Thanks In Advance

CodePudding user response:

there are several solutions:

a) use manufacturer id to get access to logo;

b) use manufacturer name to provide logo, but in this case you need to load manufacturer relation every time;

c) use image field to provide logo url based on manufacturer when creating Vehicle model (in other variants you don't need image field in Vehicle model or it can be used to provide vehicle photo not the manufacturer logo);

d) upload logo when creating/updating Manufacturer to use it (based on your manufacturer table migration - this is the one you want).

so

a) steps:

  1. upload bunch of logos into public/logo folder with relevant to car manufacturer id like 1.png, 2.png etc in whatever way you want (either manually or with some form with upload request)
  2. in your Vehicle model create getter to get access to logo url
  3. in controller use created in step 2 getter to provide displaying of associated logo
// Vehicle Model
public function getLogoUrlAttribute() {
  $path = "logo/$this->make.png";
  return Storage::exists($path) ? Storage::url($path) : '';
}

// controller fetchAll() method
...
  <td><img src="$vehicle->logo_url"  ></td>
...


b) steps:

  1. upload bunch of logos into public/logo folder with relevant to car manufacturer name like wv.png, audi.png etc in whatever way you want (either manually or with some form with upload request)
  2. in your Vehicle model create getter to get access to logo url
  3. in controller use created in step 2 getter to provide displaying of associated logo
// Vehicle Model
public function getLogoUrlAttribute() {
  if (!$this->relationLoaded('manufacturer') {
    return '';
  }
  $name = $this->manufacturer-> manu_name;
  $path = "logo/$name.png";
  return Storage::exists($path) ? Storage::url($path) : '';
}

// controller fetchAll() method
...
  <td><img src="$vehicle->logo_url"  ></td>
...


c) steps:

  1. upload bunch of logos into public/logo folder with relevant to car manufacturer id like 1.png, 2.png etc in whatever way you want (either manually or with some form with upload request)
  2. when creating new vihecle set path to logo into image field
// store() method
/* you don't need this anymore 
$file = $request->file('image');
$filename = time(). '.' .$file->getClientOriginalExtension();
$file->storeAs('public/images', $filename);*/
  $path = Storage::exists('logo/$request->make.png') ?  "logo/$request->make.png" : '';
  $vehicle = Vehicle::create(
     [
       'make' => $request->make,
       'model_name' => $request->model_name,
       'version' => $request->version,
       'powertrain' => $request->powertrain,
       'trans' => $request->trans,
       'fuel' => $request->fuel,
       'model_year' => $request->model_year,
       'image' => $path
     ]
  );

// fetchAll() method
...
<td><img src="Storage::url($vehicle->image)"  ></td>
...

of make it even better

//Vehicle model
public function getLogoUrlAttribute() {
  return Storage::url($this->image);
}

// fetchAll() method
...
<td><img src="$vehicle->logo_url" ></td>
...

d) steps:

  1. when creating Manufacturer you uploading its logo (save it with whatever you want name as it will be tied by path)
  2. get logo url from preloaded manufacturer relation
// ManufacturerController
public function store() {
  // create new manufacturer and store provided logo image
}

// Vehicle model
public function manufacturer() {
  return $this->hasOne(Manufacturer::class, 'make', 'id');
}

// Manufacturer model
public function getLogoUrlAttribute() {
  return Storage::url("logs/$this->manu_logo.png");
}

// vehicle controller
public function fetchAll() {
  // note preloading manufacturer relation
  $vehicles = Vehicle::with('manufacturer')->get();
...
  <td><img src="" . $vehicle->manufacturer->logo_url ></td>
...
}

and just to be sure avoiding n 1 request problem i'd suggest still use getter in Vehicle model for logo

// adding to Vehicle model
public function getLogoUrlAttribute() {
  if (!$this->relationLoaded('manufacturer') {
    return '';
  }
  $name = $this->manufacturer->manu_logo;
  $path = "logo/$name.png";
  return Storage::exists($path) ? Storage::url($path) : '';
}
// fetchAll() method
...
  <td><img src="$vehicle->logo_url" ></td>
...


some thoughts about your fetchAll() method: i'd suggest you to let blade build page for you - this will make controller nice and clear

public function fetchAll() {
  // note preloading manufacturer relation
  $vehicles = Vehicle::with('manufacturer')->get();
  return view('vehicle-index', ['$vehicles'=>$vehicles]);
}

and all html stuff in vehicle-index.blade.php with much more pleasant to work with

<html lang="{{ app()->getLocale() }}">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <meta name="Cache-Control" content="no-cache, no-store, must-revalidate" />
  <meta name="Pragma" content="no-cache" />
  <meta name="Expires" content="0" />

  <title>title</title>

  <!-- CSRF Token -->
  <meta name="csrf-token" content="{{ csrf_token() }}">
</head>

<body>
  @if ($vehicles->isEmpty())
  <h1 >No vehicles in the database!</h1>
  @else
  <table >
    <thead>
      <tr>
        <th >ID</th>
        <th >Image</th>
        <th >Make</th>
        <th >Model</th>
        <th >Derivative</th>
        <th >Powertrain</th>
        <th >Transmission</th>
        <th >Fuel Type</th>
        <th >Model Year</th>
      </tr>
    </thead>
    <tbody>
      <tr >
        <td>{{ $vehicle->id }}</td>
        <td><img src="{{ $vehicle->logo_url }}" ></td>
        <td>{{ $vehicle->make }}</td>
        <td>{{ $vehicle->model_name }}</td>
        <td>{{ $vehicle->version }}</td>
        <td>{{ $vehicle->powertrain }}</td>
        <td>{{ $vehicle->trans }}</td>
        <td>{{ $vehicle->fuel }}</td>
        <td>{{ $vehicle->model_year }}</td>
        <td>
          <a href="#" id="{{ $vehicle->id }}"  data-bs-toggle="modal" data-bs-target="editVehicleModal"><i ></i></a>

          <a href="#" id="{{ $vehicle->id }}" ><i ></i></a>
        </td>
      </tr>
    </tbody>
  </table>
  @endif

</body>
  • Related