Facing a problem on submit form data.
When I fill up all form data then it is inserted into the database. But when I fill only mandatory field data and leave other data as blank it is not working and it redirect to the same form.
On removing validation also not working.
My controller function code:
public function save(Request $request) {
try {
$validator = Validator::make($request->all(), Activity::rules());
$activity = Activity::saveOrUpdate($request);
if($activity !== false) {
return redirect()->route('lists-activity')->with('success', trans('activity data added successfully.!!'));
} else {
return back()->with('error', "Unable to save activity data.!!")->withInput();
}
} catch (\Exception $ex) {
return back()->with('error', "Unable to save activity data.!!")->withInput()->withErrors($validator);
}
}
My model code :
namespace App;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
class Activity extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'category_id',
'title',
'description',
'country_id',
'city_id',
'latitude',
'longitude',
'addressOne',
'addressTwo',
'hours_recomended',
'hours_fixed',
'time_fixed',
'start_time',
'end_time',
'file_type',
'flag_image'
];
/**
* Indicates if the model should be timestamped.
*
* #var bool
*/
public $timestamps = false;
public static function rules() {
return [
'category_id' => 'required',
'title' => 'required|string|max:255',
'country_id' => 'required',
'city_id' => 'required',
'hours_fixed' => 'required',
'start_time' => 'required',
'end_time' => 'required'
];
}
public static function saveOrUpdate(Request $request) {
try {
$id = $request->get('id', false);
$activity = false;
DB::transaction(function () use ($request, &$activity, $id) {
$activity = $id ? Activity::findOrFail($id) : new Activity();
$activity->fill($request->all());
try {
$activity->save();
} catch (\Exception $ex) {
throw $ex;
}
});
return $activity;
} catch (\Exception $ex) {
throw $ex;
}
} }
Form view :
Don't know what I am doing wrong?
Looks like validation works and redirects back as it supposes to do.
Put {{ dump($errors->all()) }} to the view and you'll see errors in the form after submitting the form.
Also, use the updateOrCreate() which does exactly what you're trying to do and will help you to avoid errors:
public static function saveOrUpdate(Request $request) {
return $this->updateOrCreate(['id' => $request->id], $request->all());
}
Related
I am trying to write a custom message for a validation in laravel.
I have checked online and I saw some post where others solve that same issue by adding a protected function. I have also added the function to my code but it is not working. This is my code
This is myFormController.php:
public function req(RegistrationRequest $request){ $validated =
$request->validated();
return $validated; )}
This is the RegistrationRequest.php:
use Illuminate\Contracts\Validation\Validator; use
Illuminate\Http\Exceptions\HttpResponseException;
public function authorize()
{
return true;
}
public function rules()
{
return [
'email' => 'required|email',
'firstname' => 'required|string|max:20',
'lastname' => 'required|string|max:50',
'password' => 'required|min:8',
];
} protected function failedValidation(Validator $validator) {
throw new HttpResponseException(response()->json($validator->errors(), 422)); }
When that did not work, I used this:
protected function
failedValidation(\Illuminate\Contracts\Validation\Validator
$validator) { throw new
\Illuminate\Validation\ValidationException(response()->json($validator->errors(),
422)); }
Please what am I doing wrongly?
If you want custom messages just override messages method you just need to return an array containing key value pairs of field_name => 'message'
/**
* Get custom messages for validator errors.
*
* #return array
*/
public function messages()
{
return [
'field_name.required' => 'field_name is requeired',
'field_name.max' => 'max length should be something.'
];
}
Request Class
class LoginRequest extends FormRequest
{
public function wantsJson() {
return true;
}
public function authorize() {
return true;
}
public function rules() {
$validators = [
'email' => 'required',
'password' => 'required'
];
return $validators;
}
public function failedValidation(\Illuminate\Contracts\Validation\Validator $validator) {
if($validator->fails()) {
//print_r($validator->errors());
//die();
}
return parent::failedValidation($validator);
}
}
I have an api written in Laravel. I am trying to test the validation through Postman extension. When I submit some values of email and password, it works. I get the message that the credentials exists or not.
In case, I don't submit the values, then, there is no json messagebag returned.
I can confirm that there are validation error messages in MessageBag. Here is the screenshot. If the screenshot is not clear then please click it see it.
Another strange things is that the status code returned is 200
Please let me know if you need more info
In my situation I setup my Laravel API like this.
in my App\Exceptions\Handler
public function render($request, Exception $exception)
{
// return parent::render($request, $exception);
$rendered = parent::render($request, $exception);
if ($exception instanceof ValidationException) {
$json = [
'error' => $exception->validator->errors(),
'status_code' => $rendered->getStatusCode()
];
} elseif ($exception instanceof AuthorizationException) {
$json = [
'error' => 'You are not allowed to do this action.',
'status_code' => 403
];
}
else {
// Default to vague error to avoid revealing sensitive information
$json = [
'error' => (app()->environment() !== 'production')
? $exception->getMessage()
: 'An error has occurred.',
'status_code' => $exception->getCode()
];
}
return response()->json($json, $rendered->getStatusCode());
}
also import this on top
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
It helps to format the errors into JSON format.
My LoginRequest looks like this (simple)
class LoginRequest 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
*/
public function rules()
{
return [
'email' => 'required|email',
'password' => 'required'
];
}
}
I have a login functionality from Web and also from API. I have created one Request file where I have written rules for this. For web, it is working perfectly and given output as expected but when I use it in API controller it redirects me to the login page, it should return JSON response.
One more thing, I want to add extra parameter "status" as it is failed or succeeds.
Here is my code
Request File
public function rules()
{
return [
'username' => 'required',
'password' => 'required'
];
}
API controller
public function login(Request $request)
{
$response = array();
$validator = Validator::make($request->all(), [
'username' => 'required',
'password' => 'required'
]);
if ($validator->fails()) {
$response['status'] = false;
$response['message'] = $validator->messages();
return Response::json($response);
}
try {
$username = trim($request->username);
$password = trim($request->password);
$isAuth = $this->userRepository->login($username, $password);
if ($isAuth) {
$user = Auth::user();
$response['status'] = true;
$response['message'] = Lang::get('custom.auth_success');
$response['user_detail'] = $user;
} else {
$response['status'] = false;
$response['message'] = Lang::get('auth.failed');
}
} catch (\Exception $e) {
$response = array();
$response['status'] = false;
$response['message'] = Lang::get('custom.something_wrong');
}
return Response::json($response);
}
and Web controller
public function checkAuth(UserAuthenticate $request)
{
try {
$username = trim($request->username);
$password = trim($request->password);
$isRemember = false;
if (isset($request->remember) && $request->remember == 'on') {
$isRemember = true;
}
$isAuth = $this->userRepository->login($username, $password, $isRemember);
if ($isAuth) {
return redirect('programs');
} else {
return redirect('login')->withInput()->withErrors(['username' => Lang::get('auth.failed')]);
}
} catch (\Exception $e) {
return redirect('login')->withInput()->withErrors(['error' => Lang::get('custom.something_wrong')]);
}
}
Route/web.php
Route::group(['middleware' => ['guest']], function () {
Route::get('login', ['as' => 'login', 'uses' => 'Front\UserController#login']);
});
Route/api.php
Route::post('user/authenticate', 'API\UserController#login');
I looked for the solutions but didn't found anything
Edit: if you want to use extends Request for both validators do the web validation through ajax
Since you're using passport you already have the token so you can skip login
For api your validator needs to extend Request instead of FormRequest
You can't use the same validator, because the web validator extends FormRequest and that return html. Two validators are necessary, there is no way around it.
use App\Http\Requests\Request;
class YourApiRequest 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()
{}....
In your normal web request you would have
use Illuminate\Foundation\Http\FormRequest;
class YourWebRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return \Auth::check();
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{....
In Handler.php you need to add something to the render method (if you return json from your api)
If you do not prefix your routes with api/ then figure out how to check if you are in api
if (strpos($prefix, 'api') !== false) {
if ($exception instanceof ValidationException) {
return response()->json(['success' => false, 'error' => $exception->errors(), 'data' => null], 200);
}
return response()->json(['success' => false, 'error' => $exception->getMessage(), 'data' => null], 200);
}
You may try to over ride the Laravel form request validation's failedValidation() method.
public function failedValidation(Validator $validator)
{
//wantsJson() that checks Accept header of the request and returns TRUE if JSON was requested.
if ($this->wantsJson()) {
throw new HttpResponseException(response()->json(["response" => [
'msg' => $validator->errors()->all(),
]]));
}
}
[Not tested on api calls]
When i work on locally upload image on folder works perfect but when i try to upload image on amazon web server file not uploaded and back with same page.Is there any problem with my code ?
Here is my controller function to save data :
// CountryController
public function save(Request $request) {
try {
$file = $request->file('flag_image');
$this->validate($request, Country::rules());
//$request->validate(Country::rules());
/*Image Upload code*/
If(Input::hasFile('flag_image')){
$file = Input::file('flag_image');
$destinationPath = public_path(). '/images/admin/country/';
$filename = $file->getClientOriginalName();
$image = time().$filename;
$file->move($destinationPath, $image);
$imgpath = 'images/admin/country/'.$image;
}
if($file !="") {
$request->merge(['flag_image' => $imgpath]);
}
/*Image Upload code end*/
$country = Country::saveOrUpdate($request);
if($file !="") {
$country->flag_image = $imgpath;
$country->save();
}
if($country !== false) {
return redirect()->route('lists-country')->with('success', trans('Country data added successfully.!!'));
} else {
return back()->with('error', "Unable to save country data.!!")->withInput();
}
} catch (\Exception $ex) {
return back()->with('error', "Unable to save country data.!!")->withInput();
}
}
And my model code look like:
//country model
namespace App;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
class Country extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
'short_name',
'flag_image',
'status'
];
const STATUSES = [
'Active' => 'Active',
'Inactive' => 'Inactive',
];
const DEFAULT_STATUS = 'Active';
/**
* Indicates if the model should be timestamped.
*
* #var bool
*/
public $timestamps = false;
public static function rules() {
return [
'title' => 'required|string|max:255',
'short_name' => 'required',
'status' => 'required|string|in:' . implode(",", Country::STATUSES)
];
}
public static function saveOrUpdate(Request $request) {
try {
$id = $request->get('id', false);
$country = false;
DB::transaction(function () use ($request, &$country, $id) {
$country = $id ? Country::findOrFail($id) : new Country();
$country->fill($request->all());
try {
$country->save();
} catch (\Exception $ex) {
throw $ex;
}
});
return $country;
} catch (\Exception $ex) {
throw $ex;
}
} }
What's the problem i didn't find anything.
We are working on two laravel projects one for front end laravel and for backend api. I followed tutorials on connecting this two projects but make use of guzzlehttp. However I am getting undefined index password. I already dd the user['data'] in getUsers method and gettign the correct password. Can any one help me on this.
ApiUserProvider
<?php
namespace App\Auth;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Http\Request;
use GuzzleHttp\Client;
class ApiUserProvider implements UserProvider
{
public function retrieveByCredentials(array $credentials)
{
$user = $this->getUserByUsername($credentials['username']);
return $this->getApiUser($user);
}
public function retrieveById($identifier)
{
$user = $this->getUserById($identifier);
return $this->getApiUser($user);
}
public function validateCredentials(UserContract $user, array $credentials)
{
return $user->getAuthPassword() == bcrypt($credentials['password']);
}
protected function getApiUser($user)
{
if ($user !== null) {
return new ApiUser($user);
}
}
protected function getUsers()
{
$client = new Client(['base_uri' => 'http://127.0.0.1:80/api.kourse/public/api/v1/']);
$response1 = $client->request('POST', 'oauth/access_token', [
'form_params' => [
'client_id' => 'id1',
'client_secret' => 'secret1',
'grant_type' => 'password',
'username' => 'email#yahoo',
'password' => 'password'
]
]);
$location = json_decode($response1->getBody(), true);
$token = $location['access_token'];
// Send a request to https://foo.com/api/test
$response2 = $client->request('GET', 'users/self', [
'headers' => [
'Authorization' => 'Bearer '. $token
]
]);
$user = json_decode($response2->getBody(), true);
return $user['data'];
}
protected function getUserById($id)
{
$user = [];
if($this->getUsers()['email'] == $id){
$user['id'] = $id;
}
dd($user);
return $user ?: null;
}
protected function getUserByUsername($username)
{
$user = [];
if($this->getUsers()['email'] == $username){
$user['email'] = $username;
}
return $user ?: null;
}
// The methods below need to be defined because of the Authenticatable contract
// but need no implementation for 'Auth::attempt' to work and can be implemented
// if you need their functionality
public function retrieveByToken($identifier, $token) { }
public function updateRememberToken(UserContract $user, $token) { }
}
ApiUser
namespace App\Auth;
use Illuminate\Auth\GenericUser;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
class ApiUser extends GenericUser implements UserContract
{
public function getAuthIdentifier()
{
return $this->attributes['id'];
}
}
UserController
public function login(Request $request)
{
$email = $request->email;
$password = bcrypt($request->password);
if (Auth::attempt(['username' => $email, 'password' => $password])) {
return "hello";
}
}
error
AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any application authentication / authorization services.
*
* #param \Illuminate\Contracts\Auth\Access\Gate $gate
* #return void
*/
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
Auth::provider('api', function($app, array $config) {
return new ApiUserProvider($config['model']);
});
}
}
My best guess would be to open then User model and if you have:
protected $hidden = [
'password',
'remember_token',
];
to make it an empty array, like this protected $hidden = [];. I guess this might work because when you make new ApiUser return new ApiUser($user); it's converting the User object to array and it removes the password attribute because of the $hidden property.