How to run more logic after user registration in Laravel 5 - php

I am using the default user registrar in Laravel 5. When the user registers there is some information stored in the session so after the user has been created I want to run some code to process the session data, store it and link it to the user. Would I just amend the create method in the registrar from this:
public function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password'])
]);
}
to this:
public function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password'])
]);
// do my other logic to process session data here
return $user;
}
Or is there a better way to do it?

You can use a model event, place this code in your model.
public static function boot()
{
static::created(function($model)
{
//do other logic here
});
}
http://laravel.com/docs/5.0/eloquent#model-events
You can also opt for a model observer:
<?php namespace App\Observers;
use Illuminate\Database\Eloquent\Model as Eloquent;
class UserObserver {
public function created(Eloquent $model)
{
//do other logic
}
}
You'll need a listener to this observer:
\App\User::observe(new \App\Observers\UserObserver);
You can place the listener in the routes.php file to test it.
Later on you can move the listener to a more appropriate location such as a ServiceProvider.
http://laravel.com/docs/5.0/eloquent#model-observers

Related

How to insert to database user with default value?

I want to register user and I have 3 fields in form; login, password and confirm_password. In database I have column login, password and role. So I want to insert database user which have default role User. This oode below show me error SQLSTATE[HY000]: General error: 1364 Field 'role' doesn't have a default value. How can I resolve this problem ?
You need to add/modify the Role column with your SQL Client, chances are you have not defined a default value to it, and the column is a "Not Null" one meaning you can't insert a row if this column is empty.
Another option is to have something like that with your create function :
$user = User::create([
'login' => $data['login'],
'password' => Hash::make($data['password']),
'role' => "User"
]);
If you create users only with role "User" you can add this line when you create user;
protected function create(array $data)
{
$user = User::create([
'login' => $data['login'],
'password' => Hash::make($data['password']),
'role'=>"User"
]);
$user->assignRole('role');
return $user;
}
Or you can use Observer:
class UserObserver
{
/**
* Handle the "User" created event.
*
* #param User $user
* #return void
*/
public function creating(User $user)
{
if (is_null($user->role)) {
$user->role= "User";
$user->save();
}
}
}
Controller Logic:
$user = User::create([
'login' => $request->login,
'password' => Hash::make($request->password)]);
Model Logic if you want to insert default value
class User extends Model
{
public static function boot()
{
parent::boot();
self::creating(function ($model) {
$model->role='user';
});
}
}

How can I implement laravel migration test before laravel migrate?

While writing unit tests for my migrations, I noticed that it does not check if the table it is depends on for columns with foreign keys exists. Then i decided to add a new function to my test case for cheched the table which is the depends on my new migration. New function like this;
public function test_users_table_has_foreign_keys()
{
$this->assertTrue(Schema::hasTable('workareas'));
}
But these assertions do not work parallel to migration sequence. Therefore, when I migrate, I cannot determine whether it will give an error or not with the test process. Testcase does not fail even if migration sequence is wrong.
Before adding the 'public function test_users_table_has_foreign_keys' function, my test scenario was as follows;
<?php
namespace Modules\SYS\Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
use Modules\SYS\Entities\User;
use Illuminate\Support\Str;
class UsersTest extends TestCase
{
use RefreshDatabase;
private $columns = [
'id',
'name',
'email',
'email_verified_at',
'password',
'type',
'remember_token',
'created_at',
'updated_at'
];
public function test_users_database_has_expected_columns()
{
$this->assertTrue(
Schema::hasColumns('users', $this->columns)
);
}
public function test_users_table_columns_matched()
{
$this->assertTrue(sizeof(array_diff(Schema::getColumnListing('users'), $this->columns)) == 0);
}
public function test_user_has_been_created()
{
$this->create_user();
$this->assertDatabaseCount('users', 1);
}
public function test_user_has_been_updated()
{
$user = $this->create_user();
$user->name = 'Updated Name';
$user->save();
$this->assertTrue($user->name == 'Updated Name');
}
public function test_user_has_been_deleted()
{
$user = $this->create_user();
$user->delete();
$this->assertDatabaseCount('users', 0);
}
private function create_user()
{
return
User::create([
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'type' => 'admin'
]);
}
}
i have a lot of tables and relations so i need to detect if i am making mistakes with testcases.
What kind of test scenario should I prepare to determine the accuracy of the migration sequence?

How to create a callback in laravel validation when it failed-validated and passed-validated?

I have here a validation in my custom request file.
class AuthRequest extends FormRequest
{
public function store()
{
return $this->validate([
'first_name' => ['required','min:2','max:30',new PersonNameRule],
'last_name' => ['required','min:2','max:30',new PersonNameRule],
'username' => ['required','confirmed',new UsernameRule]
]);
}
public function rules(){ return []; }
}
In my controller, this is how use it.
public function store(AuthRequest $request)
{
$data = $request->store();
return request()->all();
}
My question is how can I do these things below:
when validation failed - create a session / session(['attempt' => session('attempt')+1 ?? 1]);
when validation passed - destroy the session / session()->forget('attempt')
#mrhn is right you did not fill the rules inside the function, so the FormRequest will always return false. What you did instead, you prefer to create your own method(s) and by using the $this->validate().
Now here's how to achieve your problem, in file ..\Illuminate\Validation\Validator.php find the validate() function, and put those session you desired to perform, like these below.
public function validate()
{
if ($this->fails()) {
session(['attempt' => session('attempt')+1 ?? 1]);
throw new ValidationException($this);
}else{
session()->forget('attempt');
}
return $this->validated();
}
The solution above is global which means it will perform everytime you use $this->validate().
You can use Validator instance instead of calling validate()
$validator = Validator::make($request->all(), [
'first_name' => ['required','min:2','max:30',new PersonNameRule],
'last_name' => ['required','min:2','max:30',new PersonNameRule],
'username' => ['required','confirmed',new UsernameRule]
]);
if ($validator->fails()) {
// create a session
} else {
// destroy the session
}
You can see more in the doc here: https://laravel.com/docs/7.x/validation#manually-creating-validators
Firstly i will convert your validation to a form request, this will automatically resolve when injected into a controller.
UserCreateRequest extends FormRequest {
public function rules() {
'first_name' => ['required','min:2','max:30',new PersonNameRule],
'last_name' => ['required','min:2','max:30',new PersonNameRule],
'username' => ['required','confirmed',new UsernameRule]
}
}
To use it inject it like so.
public create(UserCreateRequest $request) {
...
}
Here you can utilize two callback methods passedValidation() and failedValidation(), in your form request.
protected function failedValidation(Validator $validator) {
session(['attempt' => session('attempt')+1 ?? 1]);
return parent::failedValidation($validator);
}
protected function passedValidation() {
session()->forget('attempt')
return parent::passedValidation();
}

Override Backpack validation roles

What I did:
I am trying to override backpack form validation roles (update request).
UserUpdateCrudRequest.php
use App\Http\Requests\Backpack\PermissionManager\UserUpdateCrudRequest as UpdateRequest;
class UserUpdateCrudRequest extends \Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest
{
function __construct()
{
parent::__construct();
}
public function authorize()
{
// only allow updates if the user is logged in
return \Auth::check();
}
public function rules()
{
$rules = [
'name' => 'required',
'password' => 'confirmed',
];
return $rules;
}
}
app/Http/Controllers/Admin/Backpack/PermissionManager/UserCrudController.php
public function update(UpdateRequest $request)
{
//code
}
What I expected to happen:
The email field is mandatory on create , and not mandatory on update.
What happened:
ErrorException in UserCrudController.php line 18:
Declaration of App\Http\Controllers\Admin\Backpack\PermissionManager\UserCrudController::update() should be compatible with Backpack\PermissionManager\app\Http\Controllers\UserCrudController::update(Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest $request)
If I'm right,
inside UserCrudController you have,
use Backpack\PermissionManager\app\Http\Requests\UserStoreCrudRequest as StoreRequest;
use Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest as UpdateRequest;
If you want to make the email field not mandatory on update you have to edit the UserUpdateCrudRequest.php inside your-project/vendor/backpack/permissionmanager/src/app/Http/Requests and remove the line
'email' => 'required',

How to auto fill foreign key column value in Laravel 5.2?

I'm working on laravel 5.2 and also beginner of laravel. I have users and clients table in the database. user field of clients table stores the value of id column(primary key) of users table. i.e, one user have many clients and one client belongs to one user. Now come to problem. When I'm going to insert new client of the logged in user, I'm getting error. No any error message. I searched and come to know that perhaps it happens because of foreign key column name is user, not user_id. So I updated my Client model from return $this->belongsTo('App\User'); to return $this->belongsTo('App\User', 'user');. But still failed. If any one knows the answer, answer will be appreciated. Here is my code.
ClientController (Try 1)
$request->user()->clients()->create([
'user' => $request->user()->id,
'email' => $request->email,
'age' => $request->age
]);
ClientController (Try 2)
$request->user()->clients()->create([
'email' => $request->email,
'age' => $request->age
]);
Client Model
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Ak\Scopes\AgeScope;
class Client extends Model
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AgeScope);
}
public function user()
{
return $this->belongsTo('App\User', 'user');
}
}
User Model
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $fillable = [
'name', 'email', 'password', 'country'
];
protected $hidden = [
'password', 'remember_token',
];
protected $date = ['deleted_at'];
public function client()
{
return $this->hasMany('App\Client', 'user');
}
}
sorry your relationship is wrong. and moreover you are using
$request->user()->clients()
instead of
$request->user()->client()
the client in your relationship is singular. And the client function body should be
return $this->hasMany('App\Client', 'user');
and in your client model add
$fillable = ['email', 'age', 'user'];
and change the user function in your client model to
public function user()
{
return $this->belongsTo('App\User', 'user');
}
the orm should be like this
$request->user()->client()->create([
'user' => $request->user()->id,
'email' => $request->email,
'age' => $request->age
]);
Try adding protected $fillable = ['email', 'age']; to your Client model.
More on mass assignement
Edit:
try this
Routes:
Route::post('user/{user}/client', 'YourController#store');
Controller:
public function store(Request $request, User, $user){
$user->client()->create([
'user' => $request->user()->id,
'email' => $request->email,
'age' => $request->age
]);
}
Problem is Solved
Problem is solved as I have to write public $timestamps = false; in Client Mode. After it, I don't need to insert user value manually. Because laravel is doing that task itself as I have write foreign key in User and Client Models relationship. i.e, return $this->hasMany('App\Client', 'user') and return $this->belongsTo('App\User', 'user') manually.
I can't understand that what should I do for this feature of laravel. Should I cry or laugh?

Categories