12-crear controladores separados para API y Web
crear controladores separados para API y Web. Te explico por qué y te muestro cómo hacerlo:
¿Por qué separar los controladores?
Separación de responsabilidades: Cada controlador tiene un propósito específico
Mantenimiento más fácil: Cambios en API no afectan la web y viceversa
Diferentes lógicas: API necesita manejo de JSON, autenticación diferente, etc.
Mejor organización: Código más limpio y escalable
Estructura recomendada
# Controlador para Web
php artisan make:controller Web/ProductController --resource --model=Product
# Controlador para API
php artisan make:controller Api/ProductController --resource --model=Product1. Controlador para API
app/Http/Controllers/Api/ProductController.php:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Product;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(): JsonResponse
{
$products = Product::all();
return response()->json([
'success' => true,
'data' => $products,
'message' => 'Products retrieved successfully'
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric|min:0',
'stock' => 'required|integer|min:0'
]);
$product = Product::create($validated);
return response()->json([
'success' => true,
'data' => $product,
'message' => 'Product created successfully'
], 201);
}
/**
* Display the specified resource.
*/
public function show(Product $product): JsonResponse
{
return response()->json([
'success' => true,
'data' => $product,
'message' => 'Product retrieved successfully'
]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Product $product): JsonResponse
{
$validated = $request->validate([
'name' => 'sometimes|required|string|max:255',
'description' => 'nullable|string',
'price' => 'sometimes|required|numeric|min:0',
'stock' => 'sometimes|required|integer|min:0'
]);
$product->update($validated);
return response()->json([
'success' => true,
'data' => $product,
'message' => 'Product updated successfully'
]);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Product $product): JsonResponse
{
$product->delete();
return response()->json([
'success' => true,
'message' => 'Product deleted successfully'
], 204);
}
}2. Controlador para Web
app/Http/Controllers/Web/ProductController.php:
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Models\Product;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(): View
{
$products = Product::latest()->paginate(10);
return view('products.index', compact('products'));
}
/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('products.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric|min:0',
'stock' => 'required|integer|min:0'
]);
Product::create($validated);
return redirect()->route('products.index')
->with('success', 'Producto creado exitosamente.');
}
/**
* Display the specified resource.
*/
public function show(Product $product): View
{
return view('products.show', compact('product'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Product $product): View
{
return view('products.edit', compact('product'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Product $product): RedirectResponse
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric|min:0',
'stock' => 'required|integer|min:0'
]);
$product->update($validated);
return redirect()->route('products.index')
->with('success', 'Producto actualizado exitosamente.');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Product $product): RedirectResponse
{
$product->delete();
return redirect()->route('products.index')
->with('success', 'Producto eliminado exitosamente.');
}
}3. Rutas separadas
routes/web.php:
<?php
use App\Http\Controllers\Web\ProductController;
use Illuminate\Support\Facades\Route;
Route::resource('products', ProductController::class);routes/api.php:
<?php
use App\Http\Controllers\Api\ProductController;
use Illuminate\Support\Facades\Route;
Route::apiResource('products', ProductController::class);4. Form Request para validación (Opcional pero recomendado)
Para mejor organización, puedes crear Form Requests:
php artisan make:request Api/StoreProductRequest
php artisan make:request Api/UpdateProductRequestapp/Http/Requests/Api/StoreProductRequest.php:
<?php
namespace App\Http\Requests\Api;
use Illuminate\Foundation\Http\FormRequest;
class StoreProductRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric|min:0',
'stock' => 'required|integer|min:0'
];
}
}Y luego usarlo en el controlador API:
public function store(StoreProductRequest $request): JsonResponse
{
$validated = $request->validated();
$product = Product::create($validated);
return response()->json([
'success' => true,
'data' => $product,
'message' => 'Product created successfully'
], 201);
}5. Ventajas de esta estructura
Separación clara: API y Web completamente independientes
Mantenimiento fácil: Cambios en uno no afectan al otro
Escalabilidad: Puedes agregar características específicas para cada uno
Testing más fácil: Tests unitarios separados
Equipos paralelos: Diferentes equipos pueden trabajar simultáneamente
6. Ejemplo de uso con API
# Crear producto
curl -X POST http://localhost:8000/api/products \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Laptop Gaming",
"price": 1299.99,
"stock": 15,
"description": "High performance gaming laptop"
}'
# Respuesta esperada:
{
"success": true,
"data": {
"id": 1,
"name": "Laptop Gaming",
"description": "High performance gaming laptop",
"price": "1299.99",
"stock": 15,
"created_at": "2023-12-20T10:00:00.000000Z",
"updated_at": "2023-12-20T10:00:00.000000Z"
},
"message": "Product created successfully"
}Esta estructura es la mejor práctica para proyectos Laravel que necesitan tanto API como interfaz web
Comentarios
Publicar un comentario