I am very new to Laravel, and I need some help with refactoring my code. Now, method is not covered in tests in 100% because I cannot mock validator object and its responses. I have following method in my cotroller
public function store(Request $request)
{
$data = $request->only([
'name',
'email',
'message',
]);
$validator = Validator::make($data, $this->validatorRules);
if ($validator->fails()) {
return $this->response->errorFromValidator($validator);
}
$savedItem = $this->repository->store($data);
if (!$savedItem) {
return $this->response->error('Cannot save');
}
return $this->response->succesItem($savedItem);
}
I tried to inject validator in controller's constructor:
function __construct(Response $response, Repository $repository, Validator $validator)
{
$this->response = $response;
$this->repository = $repository;
$this->validator= $validator;
}
and use it in method:
$this->validator::make($data, $this->validatorRules);
but I was getting syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM). How can I abstract validator outside the method, so I can mock validator in tests?
Why are you using Validator to validate your data ?
Instead of using Validator inside your controller I suggest you to use Requests to validate your form data. From your code I can notice that your trying to save a contact form, so here my suggestion :
Run this command, this will create a ContactRequest file inside "Requests" folder :
php artisan make:request ContactRequest
ContactRequest file :
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ContactRequest extends Request
{
/**
* 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
*/
public function rules()
{
return [
'name' => 'required|min:5|max:20|alpha',
'email' => 'required|email',
'message' => 'required|max:250'
];
}
}
Note : You must set autorize to return true; to avoid not authorized error.
Your controller :
<?php namespace App\Http\Controllers;
use App\Http\Requests\ContactRequest;
class ContactController extends Controller {
function __construct(Repository $repository)
{
$this->repository = $repository;
}
public function store(ContactRequest $request)
{
return $this->repository->store($data);
}
}
In your view file you can handle errors like this :
@if (count($errors) > 0)
<div class="alert alert-danger">
<button class="close" data-close="alert"></button>
@foreach ($errors->all() as $error)
<span>{{ $error }}</span>
@endforeach
</div>
@endif
Or if you prefer showing errors one by one you can do like this :
{!! $errors->first('name', '<small class="help-block">:message</small>') !!}
{!! $errors->first('email', '<small class="help-block">:message</small>') !!}
{!! $errors->first('message', '<small class="help-block">:message</small>') !!}
Your data get stored only if data is validated by ContactRequest.
Now your method should be covered in tests and you can notice how clean your controller become.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With