Validation error messages as JSON in Laravel 5.3 REST - rest

My app is creating a new entry via a POST request in an api end point.
Now, if any validation is failed then instead of returning an error json, laravel 5.3 is redirecting the request to home page.
Here is my controller:
public function create( Request $request )
{
$organization = new Organization;
// Validate user input
$this->validate($request, [
'organizationName' => 'required',
'organizationType' => 'required',
'companyStreet' => 'required'
]);
// Add data
$organization->organizationName = $request->input('organizationName');
$organization->organizationType = $request->input('organizationType');
$organization->companyStreet = $request->input('companyStreet');
$organization->save();
return response()->json($organization);
}
If there is no issue with validation then the entity will be successfully added in the database, but if there is issue with validating the request then instead of sending all the error messages as a json response it redirects back to the home page.
How i can set the validate return type to json, so with every request if the validation failed then laravel will send all the error messages as json by default.

You can do your validation as:
$validator = \Validator::make($request->all(), [
'organizationName' => 'required',
'organizationType' => 'required',
'companyStreet' => 'required'
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422)
}

The validation used in the question looks as per the recommendation by laravel. The reason of redirection is that it throws an exception which you can easily catch using the code below. So it's better to use the recommended way of code instead of re-writing framework's code again :)
public function create( Request $request )
{
$organization = new Organization;
// Validate user input
try {
$this->validate($request, [
'organizationName' => 'required',
'organizationType' => 'required',
'companyStreet' => 'required'
]);
} catch (ValidationException $e) {
return response()->json($e->validator->errors(), 422);
}
// Add data
$organization->organizationName = $request->input('organizationName');
$organization->organizationType = $request->input('organizationType');
$organization->companyStreet = $request->input('companyStreet');
$organization->save();
return response()->json($organization, 201);
}

Related

Laminas / ZF3: Add manually Error to a field

is it possible to add manually an Error Message to a Field after Field Validation and Input Filter ?
I would need it in case the Username and Password is wrong, to mark these Fields / Display the Error Messages.
obviously in ZF/ZF2 it was possible with $form->getElement('password')->addErrorMessage('The Entered Password is not Correct'); - but this doesnt work anymore in ZF3/Laminas
Without knowing how you do your validation (there are a few methods, actually), the cleanest solution is to set the error message while creating the inputFilter (and not to set it to the element after it has been added to the form).
Keep in mind that form configuration (elements, hydrators, filters, validators, messages) should be set on form creation and not in its usage.
Here the form is extended (with its inputfilter), as shown in the documentation:
use Laminas\Form\Form;
use Laminas\Form\Element;
use Laminas\InputFilter\InputFilterProviderInterface;
use Laminas\Validator\NotEmpty;
class Password extends Form implements InputFilterProviderInterface {
public function __construct($name = null, $options = []) {
parent::__construct($name, $options);
}
public function init() {
parent::init();
$this->add([
'name' => 'password',
'type' => Element\Password::class,
'options' => [
'label' => 'Password',
]
]);
}
public function getInputFilterSpecification() {
$inputFilter[] = [
'name' => 'password',
'required' => true,
'validators' => [
[
'name' => NotEmpty::class,
'options' => [
// Here you define your custom messages
'messages' => [
// You must specify which validator error messageyou are overriding
NotEmpty::IS_EMPTY => 'Hey, you forgot to type your password!'
]
]
]
]
];
return $inputFilter;
}
}
There are other way to create the form, but the solution is the same.
I also suggest you to take a look at the laminas-validator's documentation, you'll find a lot of useful informations
The Laminas\Form\Element class has a method named setMessages() which expects an array as parameter, for example
$form->get('password')
->setMessages(['The Entered Password is not Correct']);
Note that this will clear all error messages your element may already have. If you want to add your messages as in the old addErrorMessage() method you can do like so:
$myMessages = [
'The Entered Password is not Correct',
'..maybe a 2nd custom message'
];
$allMessages = array_merge(
$form->get('password')->getMessages(),
$myMessages);
$form
->get('password')
->setMessages($allMessages);
You can also use the error-template-name Laminas uses for its error messages as key in your messages-array to override a specific error message:
$myMessages = [
'notSame' => 'The Entered Password is not Correct'
];

Laravel redirect to a named route with param returns status 200

I have the following named route with params, to which I want to redirect from a post request:
Route::get('/view-project-team/{project_request_id}', 'SinglePageController#viewProjectTeam')->name('view.project.team');
The controller where I handle the post request:
public function createProjectTeam(Request $request){
try {
$projectRequest = ProjectRequest::create(['project_title' => $request->projectTitle]);
TeamMember::whereIn('email', $request->projectTeamEmails)
->update([
'project_request_id' => $projectRequest->id
]);
$projectTeam = TeamMember::get();
/*return response()->json( [
'success'=> true,
'projectRequestId' => $projectRequest->id
]);*/
return redirect()->route('view.project.team', ['project_request_id' => $projectRequest->id ]);
} catch(\Exception $e){
return ['success' => false, 'message' => 'project team creation failed'];
}
}
And the response that I get:
In the network tab, I see 90 under Name, which obviously stands for the id and only when I hover over I see the full URL http://team-management-tool.test/view-project-team/90
It is so weird as it seems correct the way i use the redirect, no clue what can be the issue then?

Stop sending the access token with the response body in Yii2

I am developing a rest API using Yii2, the front end is developed by ionic.
the case is that when I have an action which it uses bearer authentication..
it works fine but the access token is returned with the response body which leads to an HttpErrorResponse in the client side:
SyntaxError: Unexpected token y in JSON at position 0 at Json.parse
the response is returned like this so the client is not able to parse the json
y2sSCEXqkUoVY2BjkQZqx8g3W42273Cz{"success":false,"message":"you liked it before"}
this is the behaviour code which uses the bearear authentication
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator'] = [
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
];
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => CorsCustom::className(),
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'only' => ['like', 'unlike', 'likes', 'create'],
'authMethods' => [
HttpBearerAuth::className(),
],
];
return $behaviors;
}
I want to stop sending the access token in the body or send it as a json
I think you should remove the echo $token statement from your USER model
public static function findIdentityByAccessToken($token, $type = null)
{
/* echo $token; */
return static::findOne(['auth_key' => $token]);
}
Stop echo the token before the response and you'll get your job DONE!
public static function findIdentityByAccessToken($token, $type = null)
{
/* echo $token; */
return static::findOne(['auth_key' => $token]);
}

File Upload in Rest API yii2

my controller file inside api/v1/controller/
class ProfileController extends ActiveController
{
public $modelClass = 'app\models\Profile';
public function behaviors()
{
return [
[
'class' => 'yii\filters\ContentNegotiator',
'only' =>
['index', 'view', 'createnew','update','search'],
'formats' =>
['application/json' => Response::FORMAT_JSON,],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'index' => ['get'],
'view' => ['get'],
'createnew' => ['post'],
'update' => ['put'],
'delete' => ['delete'],
'deleteall' => ['post'],
'search' => ['get']
],
]
];
}
public function actionCreatenew() {
$model = new Profile();
$model->load(Yii::$app->request->post());
$model->asset = UploadedFile::getInstance($model, 'asset');
$name = $model->user_id;
if($model->asset) {
$model->asset->saveAs('uploads/'.$name.'.
'.$model->asset->extension);
$model->asset = $model->asset->name.'.'.
$model->asset->extension;
}
if($model->save()) {
echo json_encode(array('status'=>"Success",
'data'=>$model->attributes),JSON_PRETTY_PRINT);
} else {
echo json_encode(array('status'=>"Failure",
'error_code'=>400,
'errors'=>$model->errors),JSON_PRETTY_PRINT);
}
}
}
When I try to use access this from Postman like:
POST http://localhost/myapp/api/v1/profiles
I get Invalid Parameter – yii\base\InvalidParamException
Response content must not be an array.
What is the issue?? help would be grateful!! Thanks
You can easily receive single / multi-uploaded files using HTTP POST with form-data encoding in Yii2, directly in your Yii2 Controller / action.
Use this code:
$uploads = UploadedFile::getInstancesByName("upfile");
if (empty($uploads)){
return "Must upload at least 1 file in upfile form-data POST";
}
// $uploads now contains 1 or more UploadedFile instances
$savedfiles = [];
foreach ($uploads as $file){
$path = //Generate your save file path here;
$file->saveAs($path); //Your uploaded file is saved, you can process it further from here
}
If you use Postman API client to test how your API is working, you can configure the upload endpoint to work like this for multi-file uploads:
Note: The upfile[] square brackets are important! Postman will happily let you select multiple files for upload in one slot, but this will not actually work. Doing it the way shown in the screenshot makes an array of files available to the Yii2 action, through the UploadedFile mechanism. This is roughly equivalent to the standard PHP $_FILES superglobal variable but with easier handling.
Single files can be uploaded with or without the [] square brackets after the key name. And of course you can name upfile whatever you like, for your convention.
You should use \yii\web\UploadedFile::getInstanceByName('asset'); instead of getInstance() checkout this Link

Laravel Form Request Validation Error Issue

I'm using the Form Request Validation (Laravel 5) to validate my input.
It validates my form, but when it doesn't get through the validation Laravel should return automatically an in-built error.
But it stays on the same page (without refreshing) and without showing an error, neither putting the input into the database
//Controller
public function store(StoreProjectPostRequest $request)
{
$input = $request->all();
Project::create($input);
return Redirect::route('projects.index')->with('message', 'Project created');
}
//Request
public function rules()
{
return [
'name' => 'required|max:15|alpha_num',
'slug' => 'alpha_dash|required|max:10',
];
}