Laravel 5 Documentation - route model binding - php

I'm reading Laravel 5 documentation and have some problem with understanding route model binding.
I use example code from here
So, I added line to RouteServiceProvider.php:
public function boot(Router $router)
{
parent::boot($router);
$router->model('user', 'App\User');
}
I added route:
Route::get('/profile/{user}', function(App\User $user)
{
die(var_dump($user));
});
Default Laravel user model is used.
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
}
And I have MySQL table 'users'. When I go to URL http://blog.app/profile/1, I expect to see data for user with ID 1, but I don't understand how to get actual model values. Instead I see:
Is there any special methods for getting model values? Or did I miss something?

I have the same problem here. You just get an empty instance of App\User, since you declared that in your Route::get(). The model is never loaded.
Another way to bind model to the parameter:
Route::bind('user', function($value)
{
return App\User::find($value);
});
The Closure you pass to the bind method will receive the value of the URI segment, and should return an instance of the class you want to be injected into the route.

I have had the same problem.
Look for the "$namespace" var in the "RouteServiceProvider" and try to set it blank :
protected $namespace = '';

Related

Laravel 8 belongsTo relationship not returning data on User model

I'm building a Laravel 8 API and want to automatically join user_settings onto a user whenever the User model is queried.
My thinking is that I can achieve this with the belongsTo relationship since user_settings "belongs" to a user.
However, when I attach this to my UserSetting model and query a user I'm not seeing any user settings attached to my User despite having data in the user_settings table.
Where am I going wrong?
Model: User
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class UserSetting extends Model
{
use HasFactory, SoftDeletes;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'user_settings';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id',
'theme',
'refreshButtonPlacement',
'animationSpeed',
'fetchTimeout'
];
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(UserSetting::class);
}
}
Model: User
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasFactory, Notifiable, SoftDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name',
'last_name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password'
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
'last_login_at' => 'datetime'
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* #return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
I also tried using a One To One relationship and defined a settings method on my User model but in Tinker when I ran User::findOrFail(1)->settings; I had nothing either.
Relationship setup:
class User extends Model
{
//some custom stuff
/**
* Get the phone associated with the user.
*/
public function user_setting()
{
return $this->hasOne(UserSetting::class);
}
}
class UserSetting extends Model
{
//some custom things
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
Afterwards you can use eager laoding by default, in your case you will have to add $with = ['user_setting'] to your User class.
You could also use the ->with() method, for that you will have to use either:
User::with('user_setting')->find(Auth::id());
//or
Auth::user()->with('organisation')->first()
Laravel doesn't load the relationship values in every call because of the obvious overhead. So you will either define the relationship to be loaded by default or you will have to work with the ->with() method for eager loading the relationship.
Add this method to your User model
And you can access the user settings through a dynamic attribute $user-> user_setting
on each User model instance
For more informations
https://laravel.com/docs/8.x/eloquent-relationships#one-to-one
public function user_setting(){
return $this->hasOne(UserSetting::class);
}

(E_ERROR) Too few arguments to function Symfony\Component\HttpKernel\Profiler\Profile::__construct(), 0 passed

I wanted to relate a profile model to the existing user model using the relationship belongs to and hasOne and I am getting that error.
here is my Profile.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
public function user(){
return $this->belongsTo(User::class);
}
}
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Symfony\Component\HttpKernel\Profiler\Profile;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'username', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
}
In my terminals i can get the user through the profile but cannot get the profile using user. here is the error
$user->profile
TypeError: Too few arguments to function Symfony/Component/HttpKernel/Profiler/Profile::__construct(), 0 passed in /Users/macair13/freeCodeGram/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php on line 720 and exactly 1 expected.
To fix the issue, replace the use Symfony\Component\HttpKernel\Profiler\Profile; line on top of your User.php file with use App\Profile; instead.
This is happening as you've mistakenly included the wrong class on top of your User.php file. When Laravel is trying to load the relationship, it attempts to construct a Symfony\Component\HttpKernel\Profiler\Profile object instead of constructing your intended model.
Use like below in your user model
public function profile()
{
return $this->hasOne('App\Profile', 'foreign_key');
}
I am not sure why you have used Symfony\Component\HttpKernel\Profiler\Profile in your user model. When your relationship is building it is using that Profile and not your Profile Model. You have to use the Profile Model namespace while defining the relationship.

Overwrite default password reset process in Laravel 5.3

I am currently writing an application that is using Laravel 5.3 on the backend, and I'm looking for a way to overwrite the default password reset behaviour.
The class that I need to change is "ResetPassword" located here:
/Illuminate/Auth/Notifications/ResetPassword.php
Reason for the change is, that the reset url generated in this file is not correct for my front-end - as it uses url(), which puts the API url rather then the front-end url in the reset email.
You can override CanResetPassword's sendPasswordResetNotification() method in your User.php
use Illuminate\Notifications\Notifiable;
use App\Notifications\CustomResetPasswordNotification;
public function sendPasswordResetNotification($token)
{
$this->notify(new CustomResetPasswordNotification($token));
}
and create CustomResetPasswordNotification.php according your requirements.
Check Password Reset Emails section here for more details
I found a quick and easy way to overwrite the password reset process by overwriting the User class located here:
/Illuminate/Foundation/Auth/User.php
Basically, I created my own version like this:
<?php
namespace App\Traits\Auth;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use App\Traits\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements
AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
}
I saved it to /App/Traits/Auth and now use it in my User model.
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use App\Traits\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
Once finished, you can create your own version of the "CanResetPassword" trait and replace the Notification class and make necesarry adjustments.
Here is an example replacement for the "CanResetPassword" trait:
namespace App\Traits\Auth\Passwords;
use App\Notifications\CustomResetPassword as ResetPasswordNotification;
trait CanResetPassword
{
/**
* Get the e-mail address where password reset links are sent.
*
* #return string
*/
public function getEmailForPasswordReset()
{
return $this->email;
}
/**
* Send the password reset notification.
*
* #param string $token
* #return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
}

Laravel 5 setup model event to "clear up" pivot tables on model delete

I am using Laravel 5 to build a user based application. Some models have a manyToMany relationship in my app and therefore I am using pivot tables.
When I delete a user from the system, I use this simple function:
/**
* Delete user.
*
* #param $id
* #return mixed
*/
public function deleteUser($id)
{
return $this->user->whereId($id)->delete();
}
However, when the user is deleted, the rows in the pivot tables (for example role_user) do not get deleted.
I have read on the laravel site that I can use model events to "clear up" my pivot tables, but i'm really unsure how I would implement that.
Can anyone point me in the right direction?
Edit
Below is my current model setup:
namespace App\Models\User;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use App\Scopes\MultiTenantTrait;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, CanResetPassword, MultiTenantTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'user';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['cust_id', 'first_name', 'last_name', 'email', 'status', 'activation_code'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* Boot the model.
*
*/
public static function boot()
{
parent::boot();
static::deleting(function($user)
{
$user->roles()->delete();
$user->supervisors()->delete();
$user->types()->delete();
$user->rates()->delete();
$user->miscs()->delete();
});
}
...
You can add a boot method to your models, like the following:
public static function boot() {
parent::boot();
// This is a deleting event on the model
static::deleting(function($model) {
$model->... //Here your model is still available
// You could add something like this
DB::table('role_user')->where('user_id', $model->id)->delete();
})
}
But you can also extend the delete method in your models:
public function delete() {
DB::table('role_user')->where('user_id', $this->id)->delete();
parent::delete();
}

Avoid join when Auth users laravel 5

I have the following tables:
User: [id,username,password]
Producer: [id,user_id,...]
Admin: [id,user_id,...]
I've configured Authentication through User table.
So, if I get logged in when I execute Auth::user() I only can access to the user's fields. However, I would need be able to get producer's fields. I have to say that, a user can be Producer or Admin but not both.
Do you know good documentation or something to do it? Thanks a lot.
You class should hasMany relation to it
<?php namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'password'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
public function producers()
{
return $this->hasMany('Producer');
}
}
$user = Auth::user();
print_r($user->producers);

Categories