I'm trying to build a custom Artisan command with Laravel, this one can create a product by custom request and pass it to the controller to ensure that validators work fine. on the web, everything works fine, but when I run my custom command with an EMPTY field, the validators don't work and I get the integrity constraint violation error.
This is my custom command code:
<?php
namespace App\Console\Commands;
use App\Http\Controllers\Api\ProductController;
use App\Http\Requests\ProductRequest;
use App\Repositories\Interfaces\ProductRepositoryInterface;
use Illuminate\Console\Command;
class CreateProduct extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'product:create';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create new product';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$productName = $this->ask("Product name");
$productDescription = $this->ask("Product description");
$productPrice = $this->ask("Product price");
$productImageUrl = $this->ask("Product image url");
// $productRequest = new ProductRequest([
// "name" => $productName,
// "description" => $productDescription,
// "price" => $productPrice,
// "image" => $productImageUrl
// ]);
// $productRequest->setMethod('POST');
// $productRequest->replace(['foo' => 'bar']);
$productController = app()->make(ProductController::class);
$response = $productController->store(
new ProductRequest([
"name" => $productName,
"description" => $productDescription,
"price" => $productPrice,
"image" => $productImageUrl
])
);
$this->info($response);
return 0;
}
}
This my custom request code:
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
class ProductRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
"name" => "required|string|min:3|max:255",
"description" => "required",
"price" => "required",
"image" => "required|string|max:2048",
'categories.*' => "exists:categories,id"
];
}
public function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json([
'success' => false,
'message' => 'Validation errors',
'data' => $validator->errors()
]));
}
public function messages()
{
return [
"name.required" => "The name of product is mandatory",
"description.required" => "The description of product is mandatory",
"price.required" => "The price of product is mandatory",
"image.required" => "The image of product is mandatory",
];
}
}
Controller:
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\ProductRequest;
use App\Repositories\Interfaces\ProductRepositoryInterface;
use Illuminate\Http\Request;
class ProductController extends Controller
{
private $productRepository;
public function __construct(ProductRepositoryInterface $productRepository)
{
$this->productRepository = $productRepository;
}
public function index()
{
$products = $this->productRepository->all();
return response()->json($products);
}
public function create()
{
//
}
public function store(ProductRequest $productRequest)
{
$product = $this->productRepository->create($productRequest->only(['name', 'description', 'price', 'image', 'categories']));
return response()->json($product);
}
public function show($id)
{
//
}
public function edit($id)
{
//
}
public function update(ProductRequest $request, $id)
{
$productUpdated = $this->productRepository->update($request->only(['name', 'description', 'price', 'image']), $id);
return response()->json($productUpdated);
}
public function destroy($id)
{
$deleted = $this->productRepository->delete($id);
return response()->json([$deleted]);
}
public function filterProductsByCategory($id) {
$products = $this->productRepository->filterProductsByCategory($id);
return response()->json($products);
}
}
CodePudding user response:
You can merge data into the Request that is bound to the Container, which is what gets used to create the FormRequest from:
$request = app('request');
$request->replace(['your' => 'data', ...]); // or merge([...])
Then you can ask the Container for an instance of your FormRequest (which it does things to when resolving to fill it and validate it):
$productController->store(app(YourRequestClass::class));
Ideally you would not be calling a Controller like this, instead using the Container to call the method for you, so it will do dependency injection for you:
$response = app()->call('YourController@method');
Though you should really refactor this code out of the Controller and put it somewhere that your Controller and Command can both makes call to it.