Answer the question
In order to leave comments, you need to log in
How to properly organize data processing in a controller action?
I wondered about simple and flexible actions in controllers. Actually, using my approach to design, I ran into problems, for the solution of which I want to use your advice.
Examples on laravel5
Controller:
<?php
namespace App\Http\Controllers;
use App\Http\Requests\TestRequest;
use App\Services\TestService;
use Exception;
use Session;
use DB;
class TestController extends Controller
{
protected $testService;
public function __construct(TestService $testService)
{
$this->testService = $testService;
}
public function index(TestRequest $request)
{
DB::beginTransaction();
try {
$result = $this->testService->process($request->all());
if ($result) {
DB::commit();
// Данные сохранены успешно
} else {
DB::rollBack();
// Ошибка сохранения данных
}
} catch (Exception $e) {
DB::rollBack();
// Ошибка обработки данных
}
//return redirect || view;
}
}
<?php
namespace App\Services;
use ErrorException;
class TestService
{
public function process(array $data)
{
// Логика и аналитика для получания переменной $var
$var = 7;
if ($var > $data['count']) {
throw new ErrorException('Возникла критическая ошибка, ...');
}
return true;
}
}
<?php
namespace App\Http\Requests;
use HttpResponseException;
use Validator;
use Response;
class TestRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
$this->sanitize();
return [
// rules
];
}
public function messages()
{
return [];
}
public function sanitize()
{
$input = $this->all();
$input['var1'] = filter_var(isset($input['var1']) ? $input['var1'] : null, FILTER_SANITIZE_STRING);
$input['var2'] = filter_var(isset($input['var2']) ? $input['var2'] : null, FILTER_SANITIZE_STRING);
$input['var3'] = filter_var(isset($input['var3']) ? $input['var3'] : null, FILTER_SANITIZE_STRING);
$this->replace($input);
}
}
Answer the question
In order to leave comments, you need to log in
For good validation, a request should be made
<?php
namespace Vendor\Project\AppBundle\Controller;
use KoKoKo\assert\Assert;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Vendor\Project\Path\Authorization\UserNotFoundException;
use Vendor\Project\Path\Authorization\InvalidCredentialsException;
class LoginController extends Controller
{
/**
* @Route("/login", name="login")
* @Method({"POST"})
* @param Request $request
* @return JsonResponse
*/
public function loginAction(Request $request) : JsonResponse
{
try {
$login = $request->request->get('login');
$pass = $request->request->get('pass');
Assert::assert($login, 'login')->string()->notEmpty()->match('/^[a-z\d]{3,32}$/i');
Assert::assert($pass, 'pass')->string()->notEmpty()->lengthBetween(6, 32);
} catch (\Throwable $exception) {
return new JsonResponse($exception->getMessage(), JsonResponse::HTTP_BAD_REQUEST);
}
try {
$user = $this->get('UserAuthorizator')->authorize($login, $pass);
return new JsonResponse($user->getId());
} catch (UserNotFoundException $exception) {
return new JsonResponse('User not found', JsonResponse::HTTP_BAD_REQUEST);
} catch (InvalidCredentialsException $exception) {
return new JsonResponse('Invalid login or path', JsonResponse::HTTP_BAD_REQUEST);
} catch (\Throwable $exception) {
$this->get('logger')->error($exception->getMessage(), ['exception' => $exception]);
return new JsonResponse('Something went wrnog :((', JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
}
}
}
Unfortunately not. Check this: https://github.com/illuminate/validation/blob/mast...
Requests to the database go directly, so it is impossible to pass the finished model to the validator. Also have a look at this: https://github.com/illuminate/validation/blob/mast...
Also hardcoding. Laravel is not a magic wand and is far from perfect. It becomes very difficult with it when performing tasks more difficult than CRUD. But there are always options:
1) You can create your own validator class that will inherit the usual one, rewrite the verification methods from the database there, and also rewrite the DatabasePresenceVerifier so that it uses the passed model. But all this is clearly not going to be an elegant and casual solution, purely as an option.
2) Use third party validators.
3) And the easiest one is to just get the model, and then pass $model->toArray() to the validator. Thus, you can fully control what and where it comes from, as well as do different types of validations that go beyond the usual validator. But this approach also has disadvantages - some of the usual validator methods can be thrown out, such as unique and so on.
If option 3 is not suitable, which is most likely the case, then you need to look for absolutely custom verifiers.
There are no other options. Use the built-in tools Stalls - hell. I now store the UUID in binary form, so I need to unearth half of the framework here in order to implement it normally. Symfony clearly wins in this regard.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question