Skip to main content
The vehicle management system enables tracking of automotive records associated with clients. Each vehicle belongs to a single client and includes details like license plate, make, model, and manufacturing year.

Overview

Vehicles are managed through the VehiculoController located at app/Http/Controllers/VehiculoController.php:7. The system uses the Vehiculo model with a custom primary key id_vehiculo and stores data in the vehiculos table.

Model Structure

The Vehiculo model includes the following fields:

placa

License plate number - Required, unique, string

marca

Vehicle brand/make - Required, string, max 255 characters

modelo

Vehicle model - Required, string, max 255 characters

anio_fabricacion

Manufacturing year - Required, numeric, exactly 4 digits

id_cliente

Foreign key to cliente - Required, must exist in clientes table

id_vehiculo

Primary key - Auto-generated

CRUD Operations

Listing Vehicles

Retrieve all vehicles with their associated client information. Route: GET /vehiculos Controller Method: VehiculoController::index() at line 12
public function index()
{
    $vehiculos = \App\Models\Vehiculo::with('cliente')->get();
    return view('vehiculos.index', compact('vehiculos'));
}
The with('cliente') method eager loads the client relationship to prevent N+1 query problems when displaying vehicle lists.

Creating a Vehicle

Route: GET /vehiculos/createController Method: VehiculoController::create() at line 18Displays the vehicle creation form with a dropdown list of all available clients.
public function create()
{
    $clientes = \App\Models\Cliente::all();
    return view('vehiculos.create', compact('clientes'));
}
Route: POST /vehiculosController Method: VehiculoController::store() at line 24Validates and stores a new vehicle in the database.
$data = $request->validate([
    'placa' => 'required|string|unique:vehiculos,placa',
    'marca' => 'required|string|max:255',
    'modelo' => 'required|string|max:255',
    'anio_fabricacion' => 'required|numeric|digits:4',
    'id_cliente' => 'required|exists:clientes,id_cliente',
]);
Success Response: Redirects to vehiculos.index with success message “Vehículo creado correctamente.”

Viewing a Vehicle

Route: GET /vehiculos/{id} Controller Method: VehiculoController::show() at line 39
public function show(string $id)
{
    $vehiculo = \App\Models\Vehiculo::with('cliente')->findOrFail($id);
    return view('vehiculos.show', compact('vehiculo'));
}
The client relationship is eager loaded to display owner information on the vehicle detail page.

Updating a Vehicle

Route: GET /vehiculos/{id}/editController Method: VehiculoController::edit() at line 45Displays the vehicle edit form pre-filled with existing data and a dropdown of available clients.
public function edit(string $id)
{
    $vehiculo = \App\Models\Vehiculo::findOrFail($id);
    $clientes = \App\Models\Cliente::all();
    return view('vehiculos.edit', compact('vehiculo', 'clientes'));
}
Route: PUT/PATCH /vehiculos/{id}Controller Method: VehiculoController::update() at line 52Validates and updates an existing vehicle record.
$data = $request->validate([
    'placa' => 'required|string|unique:vehiculos,placa,'.$id.',id_vehiculo',
    'marca' => 'required|string|max:255',
    'modelo' => 'required|string|max:255',
    'anio_fabricacion' => 'required|numeric|digits:4',
    'id_cliente' => 'required|exists:clientes,id_cliente',
]);
The unique validation for placa excludes the current vehicle ID to allow updating the same record without triggering uniqueness errors.
Success Response: Redirects to vehiculos.index with success message “Vehículo actualizado correctamente.”

Deleting a Vehicle

Route: DELETE /vehiculos/{id} Controller Method: VehiculoController::destroy() at line 69
public function destroy(string $id)
{
    $vehiculo = \App\Models\Vehiculo::findOrFail($id);
    $vehiculo->delete();
    
    return redirect()->route('vehiculos.index')
        ->with('success', 'Vehículo eliminado correctamente.');
}

Relationships

The Vehiculo model has a many-to-one relationship with clients defined at app/Models/Vehiculo.php:20:
public function cliente()
{
    return $this->belongsTo(Cliente::class, 'id_cliente', 'id_cliente');
}
This means:
  • Each vehicle belongs to exactly one client
  • Access a vehicle’s owner using $vehiculo->cliente
  • The relationship is keyed by id_cliente on both tables
  • The foreign key constraint ensures referential integrity

Validation Rules

On Create

FieldRulesDescription
placarequired, string, unique:vehiculos,placaUnique license plate number
marcarequired, string, max:255Vehicle make/brand
modelorequired, string, max:255Vehicle model
anio_fabricacionrequired, numeric, digits:44-digit manufacturing year (e.g., 2024)
id_clienterequired, exists:clientes,id_clienteMust reference an existing client

On Update

Update validation is identical to create validation, except the unique rule for placa excludes the current record:
  • unique:vehiculos,placa,{id},id_vehiculo

Manufacturing Year Validation

The digits:4 rule ensures:
  • Exactly 4 numeric characters
  • Valid examples: 2024, 1998, 2015
  • Invalid examples: 24 (too short), 20245 (too long), 202A (not numeric)
The system does not validate whether the year is reasonable (e.g., not in the future or too far in the past). Consider adding custom validation rules if needed.

Foreign Key Constraint

The exists:clientes,id_cliente validation ensures data integrity:
'id_cliente' => 'required|exists:clientes,id_cliente'
This validation:
  • Checks that the provided client ID exists in the clientes table
  • Prevents orphaned vehicle records
  • Returns a validation error if the client doesn’t exist

Route Protection

All vehicle management routes are protected by middleware defined in routes/web.php:12:
Route::middleware(['auth', 'verified'])->group(function () {
    Route::resource('vehiculos', VehiculoController::class);
});
Users must be authenticated AND have verified their email address to access vehicle management features.

RESTful Resource Routes

The Route::resource() declaration automatically creates these routes:
MethodURIActionRoute Name
GET/vehiculosindexvehiculos.index
GET/vehiculos/createcreatevehiculos.create
POST/vehiculosstorevehiculos.store
GET/vehiculos/showvehiculos.show
GET/vehiculos//editeditvehiculos.edit
PUT/PATCH/vehiculos/updatevehiculos.update
DELETE/vehiculos/destroyvehiculos.destroy

Eager Loading Performance

The controller uses eager loading (with('cliente')) in the index() and show() methods to optimize database queries and prevent N+1 query problems.
Without Eager Loading:
// Results in N+1 queries (1 for vehicles + N for each client)
$vehiculos = Vehiculo::all();
foreach ($vehiculos as $vehiculo) {
    echo $vehiculo->cliente->nombres; // Separate query for each iteration
}
With Eager Loading:
// Results in only 2 queries (1 for vehicles + 1 for all clients)
$vehiculos = Vehiculo::with('cliente')->get();
foreach ($vehiculos as $vehiculo) {
    echo $vehiculo->cliente->nombres; // No additional queries
}

Build docs developers (and LLMs) love