Eloquent model inheritance hierarchy - laravel

I have a case where 2 eloquent models should inherit properties from a User model, but the User itself should not exist as a standalone instance. (Mentors and Students, both inherit from User class). So what I'm currently doing is:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
abstract 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',
];
/**
* Get the courses that the user has enrolled into
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function courses()
{
return $this->hasMany('App\Models\Course', 'user_course', 'user_id', 'course_id');
}
}
class Student extends User
{
protected $table = 'students';
/**
* Get the mentors that the user has hired
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function mentors()
{
return $this->hasMany('App\Models\User');
}
}
class Mentor extends User
{
protected $table = 'mentors';
/**
* Get a list of courses that a mentor is teaching
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function ownCourses()
{
return $this->hasMany('App\Models\Course', 'mentor_course', 'mentor_id', 'course_id');
}
}
I am wondering whether this is the correct to do what I am trying to accomplish?

IMHO I will use polymorhic relation:
Use three tables: users, students and mentors; in the users table add two fields: userable_id (integer), userable_type (string).
User model
class class User extends Authenticatable
{
public function userable()
{
return $this->morphTo();
}
Student model:
class Student extends Model
{
public function user()
{
return $this->morphOne('App\User', 'userable');
}
Mentor model:
class Mentor extends Model
{
public function user()
{
return $this->morphOne('App\User', 'userable');
}
Now User::find($id)->userable return a Student or a Mentor object depending on the value of the userable_type
I leave the others relations to you, I hope this helps.

Related

How can I fix User model in Laravel?

I have a custom User model in laravel. But I get errors when relationships with the User model. I couldn't find a similar problem on the internet. I have no idea what to do.
There was no User model before. I was using a model called Account and it was fine. But I updated the model name to User to use laravel's own Auth system.
Error:
Symfony\Component\ErrorHandler\Error\FatalError
Class Illuminate\Database\Eloquent\Relations\BelongsTo contains 6 abstract methods and must therefore be declared abstract or implement the remaining methods (Illuminate\Contracts\Auth\Authenticatable::getAuthIdentifierName, Illuminate\Contracts\Auth\Authenticatable::getAuthIdentifier, Illuminate\Contracts\Auth\Authenticatable::getAuthPassword, ...)
\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Relations\BelongsTo.php:12
class BelongsTo extends Relation implements \Illuminate\Contracts\Auth\Authenticatable {
My User model
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Authenticatable {
use HasFactory;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'full_name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var string[]
*/
protected $hidden = [
'password',
];
/**
* Get the blog posts for the user.
* #return HasMany
*/
public function posts(): HasMany {
return $this->hasMany(BlogPost::class, 'id', 'author_id');
}
}
BlogPost model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class BlogPost extends Model {
use HasFactory;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'author_id',
'thumbnail_id',
'title',
'slug',
'content',
'description',
'views',
];
/**
* Get the author for the blog post.
* #return BelongsTo
*/
public function author(): BelongsTo {
return $this->belongsTo(User::class, 'author_id', 'id');
}
}
users table migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up() {
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('full_name', 64);
$table->string('email', 64)->unique();
$table->string('password');
$table->softDeletes();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down() {
Schema::dropIfExists('users');
}
}
Try adding the Authorizable Trait to the User Model. Don't forget to add the use in too
use Illuminate\Foundation\Auth\Access\Authorizable;
class User extends Authenticatable
{
use Notifiable, Authorizable;

Display 2 types of data in Laravel

I have 2 types of user Athletes and Teams. I created 3 tables users,athletes & teams. I am storing username & password in users table and others information in athletes & teams table. I would like to display Athletes and Teams information in home page.
My User model is like below
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $guarded = [];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = ['password', 'remember_token',];
protected $fillable = ['email','password','remember_token','category_id'];
public function team()
{
return $this->hasOne(Team::class);
}
public function athlete()
{
return $this->hasOne(Athlete::class);
}
}
My Team model is like below
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
public $guarded = [];
protected $fillable = ['first_name','last_name','user_id','how_did_find','social_media',];
public function user()
{
return $this->belongsTo(User::class);
}
}
My Athlete model is like below
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Athlete extends Model
{
public $guarded = [];
protected $fillable = ['user_id','social_media','youtube_video','website'];
public function user()
{
return $this->belongsTo(User::class);
}
}
I am using below code in controller.
$staff_picks = User::orderBy('id','desc')->take(10)->with('athlete','team')->get();
This is how it should be
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $guarded = [];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = ['password', 'remember_token',];
protected $fillable = ['email','password','remember_token','category_id'];
public function team()
{
return $this->hasOne(Team::class);
}
public function athlete()
{
return $this->hasOne(Athlete::class);
}
}
class Team extends Model
{
public $guarded = [];
protected $fillable = ['first_name','last_name','user_id','how_did_find','social_media',];
public function user()
{
return $this->belongsTo(User::class);
}
}
class Athlete extends Model
{
public $guarded = [];
protected $fillable = ['user_id','social_media','youtube_video','website'];
public function user()
{
return $this->belongsTo(User::class);
}
}
And the query
$staff_picks = User::orderBy('id','desc')->take(10)->with('athlete','team')->get();
And the iteration
foreach($staff_picks as $r){
$r->teams->social_media; //(user can be either teams or athletes so must check for null)
$r->athletes->social_media; //(user can be either teams or athletes so must check for null)
}
In athlete & team model create a column called user_id and in user model create two methods as hasMany relation for athletes and teams models.
After login get the data as
User::where('id', 1)->with('teams', 'athletes')->first();
Relations inside User modal can be written as below.
teams() {
return $this->hasMany(Team::class);
}
athletes() {
return $this->hasMany(Athlete::class);
}

Class Not Found - Eloquent

i have these two models:
<?php namespace App\Models;
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 {
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', 'is_active'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
public function customer_details()
{
return $this->hasOne('CustomerDetails', 'user_id');
}
}
And:
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CustomerDetails extends Model {
protected $table = 'customer_details';
public function user()
{
return $this->belongsTo('User');
}
}
Now i am trying to get all customers along with their user data from the database in my index() of my UserController():
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
$users = User::with('customer_details')->get();
return [
'users' => $users
];
}
But i keep getting this error:
Fatal Error Exception Class 'CustomerDetails' not found
I have no idea what i am doing wrong here.
Your class is namespaced and should therefore be referred to as App\Models\CustomerDetails, in the $this->hasOne(...) definition of customer_details of the App\Models\User model.

Print user group name with Auth::User()->user_group->name in Laravel 4

I'm trying to display the user group name in a view using Auth::user()->user_group->name, but apparently that doesn't work as I keep getting Trying to get property of non-object.
The code goes as follow
User_Group.php Model
<?php
class User_Group extends Eloquent {
protected $table = 'user_groups';
public function users() {
return $this->hasMany('User');
}
}
User.php Model
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function user_group()
{
return $this->belongsTo('User_Group', 'user_groups_id');
}
public function getGravatarAttribute()
{
$hash = md5(strtolower(trim($this->attributes['email'])));
return "http://www.gravatar.com/avatar/$hash?s=100";
}
public function isAdmin()
{
return $this->user_groups_id == 1;
}
}
My profile.blade.php view
<small><p class="pull-right">{{ Auth::user()->user_group->name }}</p></small>
Doing the following will print the user group id reference though:
{{ Auth::user()->user_groups_id }}
Rename the method to group instead of user_group

Laravel : Trouble with belongs to into the same model

I have this model
When I try to reach the author's informations, I have
"Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$id"
"
class PostSignal extends BaseModel {
protected $fillable = [];
public function send($data)
{
$data['userid'] = $this->author()->id;
}
public function author()
{
return $this->belongsTo('User', 'user_id');
}
}
My user model is classic:
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends BaseModel implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
protected $fillable = ['username', 'email', 'password', 'last_connection', 'gravatar'];
/**
* Generate gravatar image
*
* #param integer $size Size of the image
*
* #return string Image
*/
public function gravatar($size = 32)
{
$email = md5($this->email);
return "//www.gravatar.com/avatar/{$email}?s={$size}";
}
public function Posts()
{
return $this->hasMany('BlogPost');
}
public function Comments()
{
return $this->hasMany('BlogPostComment');
}
public function signal()
{
return $this->hasmany('PostSignal');
}
}

Resources