laravel 5,update User password - php

I'm using laravel 5 to develop an app that allow every user to update his profile.
in order to update password, the user needs to first enter his old password and if the old password matched then his newly entered password will be hashed and stored in DB.
how can I validate this, using laravel form request validation?

I created a custom validator and added it to AppServiceProvider like this:
<?php
namespace App\Providers;
use Validator;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Hash ;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Validator::extend('password_hash_check', function($attribute, $value, $parameters, $validator) {
return Hash::check($value , $parameters[0]) ;
});
}
then I used it in my form request validator like this:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class UpdateUserProfileRequest extends Request
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$hashed_password = $this->user()->password ;
return [
'oldPassword'=> "password_hash_check:$hashed_password|string|min:6",
'newPassword' => 'required_with:oldPassword|confirmed|min:6',
];
}

When you want to check a Hashed value generated by
Hash::make()
you need to use
Hash::check('unhashed', $hashed)
Every time you run Hash::make('string'), a different hash is made and will not match the previous one. For example:
// Generate a hash
$password = Hash::make('password');
// $password == $2y$08$T9r9qUxrr6ejs9Ne.nLzMet8l0A8BM5QvLjhaaJasgsbMBdX4JjRu
// Generate a new hash
$new_password = Hash::make('password');
// $new_password == $2y$08$3KBlYKIMpIvk.TWwim9oPuwGA.Pzv1iF7BsDyYkz7kQlhkA/ueULe
// Compare hashes the WRONG way
$password === $new_password; // false
// Compare hash the RIGHT way
Hash::check('password', $password); // true
Hash::check('password', $new_password); // true
So Use Hash::make() method of Hash class.

I'm not sure but I think that there is no native way to do this in Laravel. If so, you can implement a custom "hash" validator:
class CustomValidator extends \Illuminate\Validation\Validator {
public function validateHash($attribute, $value, $parameters)
{
$expected = $parameters[0];
return Hash::check($value, $expected);
}
}
Register it in a provider:
class AppServiceProvider extends ServiceProvider {
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
require_once __DIR__ . '/../Http/helpers.php';
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new CustomValidator($translator, $data, $rules, $messages);
});
}
// ...
}
And use it in a form request:
class MyFormRequest extends FormRequest {
public function rules()
{
$password = Auth::user()->password;
return [
'old_password' => "required|hash:" . $password
]
}
// ...
}
Link to documentation:
http://laravel.com/docs/5.0/validation#custom-validation-rules

Related

Lumen Custom Validation

I am trying to implement a custom validation rule within lumen and I am following the docs for lumen 5.6. It says to refer to laravel validation to see how to use the validation. I am currently trying to make a validation to check if the value is a true null or not. So $x === "" would mean it fails Here is my rule located in App\Rules folder I created.
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
class TrueNull implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
if($value === "") {
return false;
} else {
return true;
}
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute cannot be an empty string.';
}
}
I copied this straight from lumen docs and make my modification to the passes function. Within my modal have
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
use Laravel\Lumen\Auth\Authorizable;
use App\Rules\TrueNull;
use Validator;
Then
public function validate($data)
{
// make a new validator object
$v = Validator::make($data,
[
'x' => ['regex:/^(?=.+)(?:[1-9]\d*|0)?(?:\.\d+)?$/', new TrueNull]
]
}
But the validation for TrueNull never happens am I missing a connection or something its really frustrating because the docs says this should work.
Here is my controller calling the update I am validating.
public function update(Request $request, $id)
{
/*
In middleware need to add community id to request.
*/
try {
$site = Site::findOrFail($id);
if ($site->validate($request->all())) {
$site->fill($request->all());
// save
$site->save();
} else {
return response()->json($site->errors(), 422);
}
} catch (Exception $e) {
return response()->json($e, 422);
}
return response()->json($site, 200);
}
For future reference I found a random snippet of code that offset the basic docs of Lumen. In my class for TrueNull instead of implements Rule I changed this to implements ImplicitRule and changed the use to \ImplicitRule and it is now catching that "" is not a null.
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\ImplicitRule;
class TrueNull implements ImplicitRule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
if($value === "") {
return false;
} else {
return true;
}
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The :attribute cannot be an empty string.';
}
}
The answer is greate by #Alexander Beyers but it doesn't work for Lumen 5.3. Here is how to create organised custom rules for the Lumen 5.3.
Create a Directory name Rules under app dir and Create the Following File:
namespace App\Rules;
use Illuminate\Support\Facades\Validator;
class AlphaSpace
{
public static function validate(){
//Extending the custom validation rule.
Validator::extend('alpha_spaces', function ($attribute, $value) {
// This will only accept alpha and spaces.
// If you want to accept hyphens use: /^[\pL\s-]+$/u.
return preg_match('/^[\pL\s]+$/u', $value);
});
}
}
Open the file resources/lang/en/validation and add the following under the Custom Validation:
Note:(under the Custom Validation is only for maintenance)
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'alpha_spaces' => 'The :attribute may only contain letters and spaces.',
Call the rule in app/Providers/AppServiceProvider::boot():
use HRM\Core\Rules\AlphaSpace;
class AppServiceProvider extends ServiceProvider
{
public function boot() {
AlphaSpace::validate();
}
// class will carry on with the stuffs!
Now you can use it anywhere you want to like this:
'first_name' => 'required|alpha_spaces|min:3|max:50',
'last_name' => 'required|alpha_spaces|min:3|max:50',
Version: Lumen 7.X
First, declare your rule in app/Providers/AppServiceProvider.php.
Create a boot() with your rule method as following (I registered a rule for phone number).
public function register()
{
//
}
public function boot()
{
app('validator')->extend('phone', function ($attribute, $value) {
return preg_match('%^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$%i', $value) && strlen($value) >= 10;
});
app('validator')->replacer('phone', function ($message, $attribute, $rule, $parameters) {
return 'Phone number has wrong format.';
});
}
Different part in opposite of Laravel, and most important is, that AppServiceProvider is not registered in Lumen by default.
You need to go to bootstrap/app.php and uncomment following line:
$app->register(App\Providers\AppServiceProvider::class);
Maybe you would like to do composer dumpautoload, just in case, but it should work without it.
Then, in your code:
$validator = Validator::make(
$request->all(),
[
'tel' => 'required|phone'
],
[
'tel.required' => 'Phone is required',
'tel.phone' => 'Phone has wrong format'
]
);
That should be it!

Laravel 5.2 send password reset after registration

I have altered my authController.php file to do a few things needed for my project. It works great, just need to make one more change. Right now the controller looks like this:
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Role;
use Mail;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\ResetsPasswords;
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins, ResetsPasswords;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/add';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* Overwrite the Laravel 5.2 standard registration
* so user will not be logged in automatically.
*
* #param array $request
* #return Register
*/
public function register(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
$this->create($request->all());
return redirect($this->redirectPath());
}
/**
* Extend password reset email to user for when registering
*/
public function sendResetLinkEmail(Request $request)
{
$this->validateSendResetLinkEmail($request);
$broker = $this->getBroker();
$this->subject = "First Time User Setup";
$broker->emailView = "auth.emails.password";
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::FIRST_TIME_SETUP:
return $this->getSendFirstTimeSetupEmailSuccessResponse($response);
case Password::INVALID_USER:
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
public function getSendFirstTimeSetupEmailSuccessResponse($response)
{
return redirect()->back()->with('status', trans($response));
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'first-name' => 'required|max:255',
'last-name' => 'required|max:255',
'phone' => 'required|max:255',
'form' => 'max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(Request $request, array $data )
{
//Create the user
$user = User::create([
'first_name' => $data['first-name'],
'last_name' => $data['last-name'],
'phone' => $data['phone'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
return $this->postEmail($request);
/*
Mail::send('auth.emails.registered', ['user' => $user], function ($m) use ($user)
{
$m->to($user->email, $user->first_name)->subject('You Have Been Added');
});*/
//Is it a User? Then give them that role
if ($data['user-role'] == 'user')
{
$role = Role::where('name', '=', 'user')->firstOrFail();
$user = User::find($user->id);
$user->roles()->attach($role->id);
}
//Is it an Admin? Then give them that role
if ($data['user-role'] == 'admin')
{
$role = Role::where('name', '=', 'owner')->firstOrFail();
$user = User::find($user->id);
$user->roles()->attach($role->id);
}
return $user;
}
}
It stops auto login on user creation, assigns a role to the user based on the form and sends a password reset email. The trouble is not I get the error Trait method guestMiddleware has not been applied, because there are collisions with other trait methods on App\Http\Controllers\Auth\AuthController
One of the tricks to this is understanding how the traits inside of the Auth factory work.
First, we'll need to use the use Illuminate\Foundation\Auth\ResetsPasswords; Trait as well as the AuthenticatesAndRegistersUsers and the ThrottlesLogins trait.
use AuthenticatesAndRegistersUsers, ThrottlesLogins, ResetsPassword;
Next, we need to make sure that we have a $request instance being passed to our create method:
protected function create(Illuminate\Http\Request $request, array $data)
Sidenote - I would recommend moving away from passing in a $data object as an argument and instead working with $request. You can get your data like this: $request->get('first-name'), etc.
Finally, we pass our $request to the postEmail() function:
return $this->postEmail($request);
This will pipe the $request to the ResetsPasswords\postEmail function:
public function postEmail(Request $request)
{
return $this->sendResetLinkEmail($request);
}
Which will inturn pipe it to the ResetsPasswords\sendResetLinkEmail function:
public function sendResetLinkEmail(Request $request)
{
$this->validateSendResetLinkEmail($request);
$broker = $this->getBroker();
$response = Password::broker($broker)->sendResetLink(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::INVALID_USER:
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
Which will ultimately send out an email.
The key to making this entire thing work is that the instance of Illuminate\Http\Request always contains an email field.
Note
The response that will be returned from the sendResetLinkEmail function may not be the same response that you sent out. Perhaps Users are confused by a Password Reset request when they've just created their account. Instead, maybe you want to send a First Time Setup. In order to do this, you will need to create your own Password Broker and Password Facade.
Next, lets make 2 new directories:
App\Brokers
App\Facades
Next, make a new file inside of App\Facades and call it Password.php. Namespace the file accordingly and extend the existing Password Facade. Also, we'll add another const as an observable response type for our FIRST_TIME_SETUP.
<?php
namespace App\Facades;
class Password extends \Illuminate\Support\Facades\Password {
/**
* Constant representing a successfully sent reminder.
*
* #var string
*/
const FIRST_TIME_SETUP = 'passwords.first_time_setup';
}
Now we have added another response type that we can switch on which will help dictate how we send out our email.
Next, we need to make our Password Broker and establish our sendFirstTimeSetup functionality.
namespace App\Brokers;
class PasswordBroker extends Illuminate\Auth\Passwords\PasswordBroker {
public function sendFirstTimeSetup(array $credentials, Closure $callback = null)
{
// First we will check to see if we found a user at the given credentials and
// if we did not we will redirect back to this current URI with a piece of
// "flash" data in the session to indicate to the developers the errors.
$user = $this->getUser($credentials);
if (is_null($user)) {
return static::INVALID_USER;
}
// Once we have the reset token, we are ready to send the message out to this
// user with a link to reset their password. We will then redirect back to
// the current URI having nothing set in the session to indicate errors.
$token = $this->tokens->create($user);
$this->emailResetLink($user, $token, $callback);
return static::FIRST_TIME_SETUP;
}
}
Now we need to copy the sendResetLinkEmail function that we saw earlier, and move it into our AuthController. This will allow us to modify the Password Facade that we use, and modify our switch statement to support our First Time Setup
public function sendResetLinkEmail(Request $request)
{
$this->validateSendResetLinkEmail($request);
$broker = $this->getBroker();
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::FIRST_TIME_SETUP:
return $this->getSendFirstTimeSetupEmailSuccessResponse($response);
case Password::INVALID_USER:
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
Then, also in the AuthController, we'll make another function to return our response:
public function getSendFirstTimeSetupEmailSuccessResponse($response)
{
return redirect()->back()->with('status', trans($response));
}
Finally, if you want to override the view that is used by the function when being sent out, simply override the $broker->emailView property before invoking the ->sendFirstTimeSetup() function:
//...
$broker->emailView = "emails.user.first_time_setup";
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
//...
If you want to change the subject of the email, override the ->subject() property inside of your AuthController prior to firing your ->sendFirstTimeSetup() function:
//...
$this->subject = "First Time User Setup";
$broker->emailView = "emails.user.first_time_setup";
$response = Password::broker($broker)->sendFirstTimeSetup(
$this->getSendResetLinkEmailCredentials($request),
$this->resetEmailBuilder()
);
//...
I could go on and on, but I think this will get you going in the right direction. Hopefully it will help a few others as well.
You can fix your trait collision issue by changing the use block to the following:
use ThrottlesLogins,
ResetsPasswords,
AuthenticatesAndRegistersUsers {
AuthenticatesAndRegistersUsers::guestMiddleware insteadof ResetsPasswords;
AuthenticatesAndRegistersUsers::getGuard insteadof ResetsPasswords;
AuthenticatesAndRegistersUsers::redirectPath insteadof ResetsPasswords;
}
It's ugly, but it will fix all related collisions, thus allowing you to just use the pre-built Illuminate methods if you so choose.

Laravel user capabilities

Within Laravel you can easily define abilities and then hook into them later on a user request regarding to do different actions:
$gate->define('update-post', function ($user, $post) {
return $user->id === $post->user_id;
});
But almost all my defined abilities has this part $user->id === $model->user_id in it. I don't like it as it's a kind of repeating a condition over and over which I think could be more abstract.
Most of my defined abilities are according to updating/deleting records, so it would be better if I could make a global condition applied to all of them or if there could be a group ability defining which is like to what we do in routing.
Is there any workaround for it? I really like it DRY.
Everything in Laravel is extendable, that's the power of its service providers.
You can extend the Gate object to a MyCustomGate object and do whatever you want in that object. Here's an example:
MyCustomGate.php
class MyCustomGate extends \Illuminate\Auth\Access\Gate
{
protected $hasOwnershipVerification = [];
/**
* Define a new ability.
*
* #param string $ability
* #param callable|string $callback
* #return $this
*
* #throws \InvalidArgumentException
*/
public function defineWithOwnership($ability, $callback, $foreignUserIdKey = "user_id")
{
// We will add this
$this->hasOwnershipVerification[$ability] = $foreignUserIdKey;
return $this->define($ability, $callback);
}
/**
* Resolve and call the appropriate authorization callback.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param string $ability
* #param array $arguments
* #return bool
*/
protected function callAuthCallback($user, $ability, array $arguments)
{
$callback = $this->resolveAuthCallback(
$user, $ability, $arguments
);
// We will assume that the model is ALWAYS the first key
$model = is_array($arguments) ? $arguments[0] : $arguments;
return $this->checkDirectOwnership($ability, $user, $model) && call_user_func_array(
$callback, array_merge([$user], $arguments)
);
}
/**
* Check if the user owns a model.
*
* #param string $ability
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param \Illuminate\Database\Eloquent\Model $model
* #return bool
*/
protected function checkDirectOwnership($ability, $user, $model)
{
if(!isset($this->hasOwnershipVerification[$ability])) {
return true
}
$userIdKey = $this->hasOwnershipVerification[$ability];
// getAuthIdentifier() is just ->id, but it's better in case the pk of a user is different that id
return $user->getAuthIdentifier() == $model->{$userIdKey};
}
}
Then, you will have to tell Laravel to use your gate instead of the default one. You ca do that in your AuthServiceProvider (assuming that it's extending Illuminate\Auth\AuthServiceProvider, just add the following method.
AuthServiceProvider
/**
* Register the access gate service.
*
* #return void
*/
protected function registerAccessGate()
{
$this->app->singleton(\Illuminate\Contracts\Auth\Access\Gate::class, function ($app) {
return new MyCustomGate($app, function () use ($app) {
return $app['auth']->user();
});
});
}
And this way, you can define abilities using defineWithOwnership() method instead of define(). You can still use define() for abilities that don't require ownership verification. There's a third parameter defineWithOwnership() accepts which is $foreignUserIdKey; that's used for the case when a model has a different field for the user id.
Note: I wrote the code on the fly and did not try it, it may have errors, but you get the idea.
I checked your question quite a bit, but I've found no "easy" way to do it.
Instead, what I would probably do is this:
<?php
namespace App\Policies;
use App\User;
use App\Post;
trait CheckOwnership {
protected function checkOwnership($user, $model) {
$owned = $user->id === $model->user_id;
if ($owned === false)
throw new NotOwnedException;
}
}
class PostPolicy
{
use CheckOwnership;
public function update(User $user, Post $post)
{
try {
$this->checkOwnership($user, $post);
//continue other checks
} catch (NotOwnedException $ex) {
return false;
}
}
}
Add this function to your AuthServiceProvider
public function defineAbilities(array $abilities, $gate)
{
foreach($abilities as $name => $model){
$gate->define($name, function ($user, $model){
return $user->id === ${$model}->user_id;
});
}
}
and then inside boot method
$this->defineAbilities(['ability1' => 'model1', 'ability2' => 'model2'], $gate);
You can define another function and call it within the anonymous function. This will allow you to have commonly-used code in one central location while still allowing any resource-specific logic.
Add this function to your AuthServiceProvider class:
public function userCheck(User $user, $target)
{
// do the user id check
$result = isset($target->user_id) && isset($user) && $user->id === $target->user_id;
return $result;
}
Your code, modified:
$gate->define('update-post', function ($user, $post) {
// call the function
$result = $this->userCheck($user, $post);
// do some kind of 'update-post' specific check
return $result/* && some_bool_statement*/;
});
I think you can use middlewares.
Simply make a admin middleware and use it in your routes and routes group.
And there is no security bug on your project (delete, create & ... actions) because Laravel has csrf token!
You can use before() function, also.
And then an important note:
if you don't define a correspond function on Policy class and call it $this->authorize($post) on a controller an unauthorized Action error will be thrown unless before()methodreturnstrue.
for example call $this->authorize on Dashboard\PostsController:
public function edit($id)
{
$post = Post::find($id)->first();
$this->authorize($post);
return view('dashboard.post')->with(compact('post'));
}
and if we defined a PostPolicy Class:
class PostPolicy
{
use HandlesAuthorization;
public function before($user, $ability)
{
return $user->is_admin;
}
}
If user be admin he/she can edit post because we returned true in before() method despite of have not a method with same name (as edit method in PostsController).
In fact Laravel will check for before method mthod on Policy Class. if before return'snull will check for correspond method with same name on controller method and if this method not found user cannot perform action.
Thank you laravel for DRY us!♥

Laravel 5 - why is input empty when returning with errors?

I have a form that submits to a controller, which validates the data. If the validation fails it redirects back with the input and the errors. This is the method that deals with the form submission:
<?php namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
class UserController extends Controller {
/**
* Create a new user.
*
* #param Reqeust $request
*
* #return Void
*/
public function postCreate(Request $request)
{
$user = new User;
$rules = $user->rules();
$rules['password'] = 'required|confirmed|min:8';
$v = \Validator::make($request->except('_token', 'roles'), $rules);
if ($v->fails())
{
return redirect()->back()->withInput($request->except('_token', 'password', 'password_confirmation'))->withErrors($v);
}
$user->fill($request->except('_token', 'password', 'password_confirmation'));
$user->password = \Hash::make($request->input('password'));
$user->save();
return redirect()->route('webmanAccounts')->with('messages', [['text' => 'User account created', 'class' => 'alert-success']]);
}
On the page that displays the form I check to see if name, one of the fields, is present and if so populate a User object with the data. The problem is input is always empty.
<?php namespace BackEnd;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Request as RequestFacade;
use App\Http\Controllers\Controller;
use App\Models\Role;
use App\Models\User;
class UserController extends Controller {
public function __construct(Request $request)
{
if ( ! $request->user()->can('accounts'))
{
return abort(403, 'You do not have permission to access this page.');
}
}
/**
* Display the create new user form and process any error messages.
*
* #param Reqeust $request
*
* #return View
*/
public function create(Request $request)
{
$user = new User;
dump(RequestFacade::all());
if (RequestFacade::has('name'))
{
$user->fill(RequestFacade::except('_token', 'roles'));
foreach (RequestFacade::only('roles') as $role)
{
$user->roles()->add($role);
}
}
return view('backend.user.create', ['title' => 'Website Manager :: Create New Account', 'user' => $user, 'roles' => Role::all()]);
}
I have tried RequestFacade, $request and Input, all show as empty. Why isn't the data being passed back?
To add to the strangeness of this, I have another project that uses almost identical code and that works perfectly fine. Why would it work fine for one project but not for another!?
When you use the withInput() method, the data is flashed to the session as "old" data.
$request->old() should give you an array of all the "old" data.
$request->old('name') should give you the "old" name data.

Custom validator in Laravel 5

I am upgrading my Laravel application from 4 to 5. However, I have a custom validator that I cannot get to work.
In L4, I made a validators.php file and included it in global.php using require app_path().'/validators.php';.
I tried doing somewhat the same in L5. I dropped a validator in app/Validators/Validators.php, and updated my composer.json.
"files": [
"app/Validators/Validators.php"
]
However, now nothing renders on any page. What've I done wrong?
Try the following:
Make a bind class where you can implement each rule you want extending Validator class.
Make a service provider that extends ServiceProvider.
Add your custom validator provider at config/app.php file.
You can create the bind at Services folder like this:
namespace MyApp\Services;
class Validator extends \Illuminate\Validation\Validator{
public function validateFoo($attribute, $value, $parameters){
return $value == "foo"
}
}
Then, use a service provider to extends the core:
namespace MyApp\Providers;
use MyApp\Services\Validator;
use Illuminate\Support\ServiceProvider;
class ValidatorServiceProvider extends ServiceProvider{
public function boot()
{
\Validator::resolver(function($translator, $data, $rules, $messages)
{
return new Validator($translator, $data, $rules, $messages);
});
}
public function register()
{
}
}
Finally, import your service provider at config/app.php like so:
'providers' => [
...
...
'MyApp\Providers\ValidatorServiceProvider';
]
so here's what I did on adding a custom validation. this is for laravel 5.1
run PHP Artisan make:request MyFormValidationRequest file is created under app\Requests\MyFormValidationRequest.php
Here's the initial code:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class MyFormValidationRequest 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 [
//
];
}
}
IMPORTANT: Change the return value of authorize() method to true, if you're not doing any authentication. it's initial value is false. else you get a white page with a "Forbidden" error message.
I added a rule under the function rules(), here's what it looks like
public function rules() {
return [
'activeuntil' => 'today_onwards'
];
}
today_onwards is my new validation.
I created a folder named 'Services' under App folder
I created a file named 'ValidatorExtended.php' under App\Services folder , here's the code below:
<?php
namespace App\Services;
use Illuminate\Validation\Validator;
use Carbon\Carbon;
class ValidatorExtended extends Validator {
private $_custom_messages = array(
"today_onwards" => "The :attribute must be today onwards",
);
public function __construct( $translator, $data, $rules, $messages = array(), $customAttributes = array() ) {
parent::__construct( $translator, $data, $rules, $messages, $customAttributes );
$this->_set_custom_stuff();
}
protected function _set_custom_stuff() {
//setup our custom error messages
$this->setCustomMessages( $this->_custom_messages );
}
protected function validateTodayOnwards( $attribute, $value ) {
$now = strtotime('-1 day');
$valueDateFormat = strtotime($value);
if($valueDateFormat > $now){
return true;
}
else {
return false;
}
}
}
Note: the validateTodayOnwards method is where you put your logic.
the name of the method should always start in "validate" then the name of your new validation key which should be in title case,
Another note your validation key should be separated by underscore and all small letters, in this case, "today_onwards". the underscore should be put before all first capital letters in the method name. I hope I explained it good.
TodayOnwards method is equivalent to validation name of "today_onwards",
another example, if I created validateOldPassword, your validation key should be "old_password".
I added below code in app\Providers\AppServiceProvider.php inside boot() method.
Validator::resolver(function($translator, $data, $rules, $messages = array(), $customAttributes = array())
{
return new ValidatorExtended($translator, $data, $rules, $messages, $customAttributes);
});
Don't forget to add below library, one is the Validator class and the other is your own class which is the "ValidatorExtended".
use App\Services\ValidatorExtended;
use Illuminate\Support\Facades\Validator;
Here's what the whole file looks like, [app\Providers\AppServiceProvider.php]
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\ValidatorExtended;
use Illuminate\Support\Facades\Validator;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
Validator::resolver(function($translator, $data, $rules, $messages = array(), $customAttributes = array())
{
return new ValidatorExtended($translator, $data, $rules, $messages, $customAttributes);
});
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
That's it. done. you created your own custom validation.
Additionally, if you want to use it in your controller, below is the code:
class testController extends Controller
{
public function updatePass(MiscValidation $request){
//code here
}
}
Instead of using Request Class you use your own class which is an extension of the Request class.

Categories