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:
- upload bunch of logos into
public/logo
folder with relevant to car manufacturerid
like 1.png, 2.png etc in whatever way you want (either manually or with some form with upload request) - in your
Vehicle
model create getter to get access to logo url - 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:
- upload bunch of logos into
public/logo
folder with relevant to car manufacturername
like wv.png, audi.png etc in whatever way you want (either manually or with some form with upload request) - in your
Vehicle
model create getter to get access to logo url - 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:
- upload bunch of logos into
public/logo
folder with relevant to car manufacturerid
like 1.png, 2.png etc in whatever way you want (either manually or with some form with upload request) - 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:
- when creating
Manufacturer
you uploading its logo (save it with whatever you want name as it will be tied by path) - 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>