Lazy eager loaded relationship missing in toArray() - laravel

Laravel 5.8
I am lazy loading an user with the related customer which has a one-to-one-relation with a crmaccount-object
The models are working so that when i retrieve the eager-loaded entity it shows all of the nested relationships.
One row later i use the "toArray()" method on that object and the output is missing the third-level-relations.
The only thing which maybe some kind of special regarding the "crmaccount"-model is that it holds a column which is json an has to be casted.
Any idea what is going on here?
All of these happens in a middleware. No difference if i use with or load.
public function handle($request, Closure $next)
{
$UserData = \Auth::user();
if($UserData){
$User = \App\Login::with(['role','customer','customer.crmaccount'])->find($UserData->id);
dump($User);
dd($User->toArray());
$UserData['isAdmin'] = false;
if($UserData['role']['name'] === 'Admin'){
$UserData['isAdmin'] = true;
}
$request->request->add(['UserData' => $UserData]);
}
return $next($request);
}
Login
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Login extends Authenticatable{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','customer_id','role_id'
];
/**
* 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 Role(){
return $this->belongsTo('App\Role');
}
public function Customer(){
return $this->belongsTo('App\Customer');
}
/**
* [hasOpportunities Ruft alle Opportunities des Users ab. Da diese lediglich zwei Entitäten weiter sind, kann anstatt von dot-notated Lazy-Load auch die hasManyThrough-ORM-Methode genutzt werden]
* #return [hasManyThrough-Relation] [Die hasManyThrough-ORM-Beziehung]
*/
public function hasOpportunities(){
return $this->hasManyThrough(
'App\Opportunity',
'App\Customer',
'id',
'customer_id',
'customer_id'
);
}
/**
* [hasSalesreps Ruft alle SalesReps des Users ab. Da diese lediglich zwei Entitäten weiter sind, kann anstatt von dot-notated Lazy-Load auch die hasManyThrough-ORM-Methode genutzt werden]
* #return [hasManyThrough-Relation] [Die hasManyThrough-ORM-Beziehung]
*/
public function hasSalesreps(){
return $this->hasManyThrough(
'App\Salesrep',
'App\Customer',
'id',
'customer_id',
'customer_id'
);
}
}
Customer
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model{
public $timestamps = false;
protected $visible = ['id','name'];
protected $fillable = ['name'];
public function crmaccount(){
return $this->hasOne('App\Crmaccount');
}
public function Salesreps()
{
return $this->hasMany('App\Salesrep');
}
public function Prospects()
{
return $this->hasMany('App\Prospect');
}
public function Trees()
{
return $this->hasMany('App\Salesreptrees');
}
public function Opportunities()
{
return $this->hasMany('App\Opportunity');
}
public function User()
{
return $this->hasMany('App\Login');
}
}
Crmaccount
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Crmaccount extends Model{
public $timestamps = false;
protected $visible = ['id','name','crm_system','customer_id','crm_api_config'];
protected $fillable = [
'name','crm_system','customer_id','crm_api_config'
];
protected $casts = [
'crm_api_config' => 'array'
];
public function customer(){
return $this->belongsTo('App\Customer');
}
}

On every model, there is a protected $visible = []; and protected $hidden = [] attribute. These control the attributes that are available when the model is converted to an object, array or json. This includes relationships, as Laravel internally converts them to attributes, so omitting them from visible, or including them in hidden will cause them to not be available.
In Customer.php:
protected $visible = ['id','name'];
Since crmaccount is not in that array, only id and name will be available. Simply add crmaccount to the array to handle:
protected $visible = ['id','name', 'crmaccount'];
Alternatively, use hidden to explicitly set the attributes you don't want to show, and relationship, if loaded via ->with() will show by default.

Related

Attempt to read property "name" on null (View: C:\xampp\htdocs\Moja_OTT\resources\views\premium\profile.blade.php)

I want a simple program that shows the user profile after login. I used session and middleware. But it is saying that the name property is null. Please help me solve this error. I have used User model. The value of the properties are not retrieving from the database.
Blade code:
<h1>Profile</h1>
<h2>Welcome Mr/Ms {{$user->name}}</h2>
Logout
Model:
<?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 App\Models\PremiumModel;
class User extends Authenticatable implements MustVerifyEmail
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $table = 'users';
protected $primaryKey = 'user_id';
protected $timestamp = false;
protected $fillable = [
'name',
'email',
'password',
'type',
'email_verified_at',
'pro_pic',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
function admin()
{
return $this->hasOne('App\Models\admin', 'user_id', 'admin_id');
}
function premium()
{
return $this->hasMany(PremiumModel::class, 'user_id', 'user_id');
}
}
Controller code:
function profile()
{
$user = User::where('user_id',session()->get('logged'))->first();
return view('premium.profile')->with('user',$user);
}
Here, logged is the middleware.
You can try hasOne in the User model:
public function premium()
{
return $this->hasOne(PremiumModel::class, 'user_id', 'user_id');
}
Because hasMany returned an array, but hasOne returned just a single Object

Round robin not functioning well

I try to create a function using round robin where all user in a group will be moderator for every meeting created.For example, a group have 2 users, I managed to create the first two meeting with the two users, but when I created the third meeting, it become null.
public function addsession(Request $req)
{
$mod = null;
$latestUserId=Meeting::where('groupID', $req->groupID)
->latest('id')
->first()
?->meetingModerator;
//the first meeting or all the users have already had their turn
$firstUserId=DB::table('group_user')
->where('group_id', $req->groupID)
->orderBy('user_id')
->first()
?->user_id;
//second time meeting is being held
if ($latestUserId) {
$nextUserId=DB::table('group_user')
->where('group_id', $req->groupID)
->where('user_id', ">", $latestUserId)
->orderBy('user_id')
->first()
?->user_id;
$mod = $nextUserId;
} else {
$mod = $firstUserId;
}
$data = new Meeting;
$data->groupID = $req->groupID;
$data->meetingDate = $req->meetingDate;
$data->meetingTime = $req->meetingTime;
$data->meetingModerator = $mod;
$data->save();
}
Model group.php
class Group extends Model
{
use SoftDeletes;
use HasFactory;
public $timestamps=true;
protected $dates = ['deleted_at'];
public function creators()
{
return $this->belongsToMany(User::class);
}
}
Model user.php
class User extends Authenticatable
{
use SoftDeletes;
use HasApiTokens;
use HasFactory;
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
'role'
];
protected $dates = ['deleted_at'];
public function grp()
{
return $this->belongsToMany(Group::class);
}
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
'two_factor_recovery_codes',
'two_factor_secret',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
'profile_photo_url',
];
}
Model meeting.php
class Meeting extends Model
{
use HasFactory;
public function gr()
{
return $this->belongsTo('App\Models\Group','groupID');
}
}

Laravel Many-to-Many relationship not working

I'm facing a strange problem with Laravel Relations.
I'd like to access an event with many users (works perfect).
<?php
$event_with_user = Event::with('registered_users')->where('id', 253)->get();
dd($event_with_user);
And I'd like to access a user with all connected events:
<?php
$user_with_event = User::with('registered_events')->where('id', 1)->get();
dd($user_with_event);
Where I always receive this error:
Illuminate\Database\Eloquent\RelationNotFoundException
"Call to undefined relationship [registered_events] on model [App\User]."
I've checked the relations multiple times, but can't find a mistake. Does anyone else had that issue?
My Models
User.php
<?php
namespace App;
use App\Event;
use App\UserType;
use App\EventUser;
use App\Department;
use App\Evaluation;
use App\UserLocation;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'fname', 'lname', 'email', 'password', 'phone', 'email_verified_at', 'admin', 'user_type_id', 'last_login_at', 'last_login_ip', 'user_location_id', 'user_notification_type_id', 'user_notification_setting_id', 'slack_user_id', 'joinpoints_user_id'
];
/**
* 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 registered_events()
{
return $this->belongsToMany(Event::class, 'event_user', 'event_id', 'user_id');
}
}
Event.php
<?php
namespace App;
use App\User;
use App\EventRoom;
use App\EventType;
use App\EventStatus;
use App\EventLocation;
use App\EventParticipant;
use App\EventParticipantItems;
use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;
class Event extends Model
{
use Sluggable;
protected $fillable = [
'event_type_id', 'user_id', 'status', 'customer', 'slug', 'datetime', 'duration','embed_chat','number_of_participants','heading', 'description_1', 'description_2', 'livestream_link', 'logo_link', 'event_password', 'participants_per_room', 'youtube_id', 'embed_code', 'session_link', 'hide_breakout', 'help_link', 'lang', 'layout', 'btn2_text', 'btn2_link', 'help_text', 'background_url', 'black_font',
];
protected $dates = ['datetime'];
public function getRouteKeyName()
{
return 'slug';
}
/**
* Return the sluggable configuration array for this model.
*
* #return array
*/
public function sluggable()
{
return [
'slug' => [
'source' => 'customer'
]
];
}
public function registered_users()
{
return $this->belongsToMany(User::class, 'event_user', 'user_id', 'event_id')->withPivot('id', 'user_status', 'eventmanager', 'created_at', 'updated_at');
}
}
My Tables:
user: id,....
event: id,...
event_user: id, user_id, event_id,...
Look a bit closer at your models :
return $this->belongsToMany(Event::class, 'event_user', 'event_id', 'user_id');
and
return $this->belongsToMany(User::class, 'event_user', 'event_id', 'user_id');
Whilst the table is right, you will need to swap the order of event_id and user_id on one of them...
Looks like you swapped the (foreign) keys:
In User.php:
public function registered_events()
{
return $this->belongsToMany(Event::class, 'event_user', 'user_id', 'event_id');
}
In Event.php:
public function registered_users()
{
return $this->belongsToMany(User::class, 'event_user', 'event_id', 'user_id')->withPivot('id', 'user_status', 'eventmanager', 'created_at', 'updated_at');
}
As you follow the correct Laravel database structure, you could simply put
return $this->belongsToMany(Event::class); in User.php and
return $this->belongsToMany(User::class)->withPivot(...); in Event.php

eloquent one-To-Many-To-Many

Hi everyone I start with Laravel and eloquent and already I have a problem.
I have users, each user can have multiple vehicles and a vehicle can have multiple rentals. I want to list all rentals of each vehicle belonging to the current user.
User model:
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',
];
public function vehicule()
{
return $this->hasMany('App\Models\Vehicule');
}
Vehicule model:
use Illuminate\Database\Eloquent\Model;
class Vehicule extends Model
{
protected $fillable = [
'user_id',
'published',
'rented'
];
public function user()
{
return $this->belongsTo('App\User');
}
public function rental()
{
return $this->hasMany('App\Models\Rental');
}
Rental model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Rental extends Model
{
protected $fillable = [
'from_date',
'to_date',
'amount_total',
'vehicule_id'
];
public function vehicule()
{
return $this->belongsTo('App\Models\Vehicule');
}
}
You can use your existing relationships:
$rentals = $user->load('vehicule.rental')->pluck('vehicule.rental')->collapse();
Or add a HasManyThrough relationship to User:
public function rental()
{
return $this->hasManyThrough(Rental::class, Vehicule::class);
}
$rentals = $user->rental;

How to relate two tables in Laravel 5.0

In a little example, I have 3 tables (2 of them are important).
My tables are PRODUCT, TRANSFER, WAREHOUSE
I want to transfer the PRODUCT from 1 WAREHOUSE to another and obviously this transfer has to be in the TRANSFER TABLE, My example model could be the next.
HERE THE ENTITY - RELATION - MODEL
Now I'm Using Laravel 5.0
And when I create the models im doing this, with TRANSFER model:
<?php namespace Sicem;
use Illuminate\Database\Eloquent\Model;
class TRANSFER extends Model{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'TRANSFER';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['id','ware_ori_id','ware_end_id','product_id'];
public function product(){
return $this->belongsTo('Sicem\Product');
}//THIS IS OK!
public function sourceware(){
return $this->belongsTo('Sicem\Warehouse\ware_ori_id');
}//I THINK THIS IS OK!
public function endware(){
return $this->belongsTo('Sicem\Warehouse\ware_end_id');
}//I THINK THIS IS OK!
}
Now, My question is here in my WAREHOUSE model, I don't what can I put:
<?php namespace Sicem;
use Illuminate\Database\Eloquent\Model;
class WAREHOUSE extends Model{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'WAREHOUSE';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['id','name'];
public function transfer(){
return $this->hasMany('Sicem\TRANSFER');
}//I supose this.
//But is or not necesary to have 2(two) functions for the relation in my TRANSFER model???????????
}
SICEM: is my project name
Please Help me.
class Product {
protected $table = 'PRODUCT';
protected $fillable = ['name'];
public function transfers()
{
return $this->hasMany(Transfer::class);
}
public function transfer($warehouse_from_id, $warehouse_to_id)
{
return Transfer::create([
'product_id' => $this->id,
]);
}
}
class Transfer {
protected $table = 'TRANSFER';
protected $filalble = ['ware_ori_id', 'ware_end_id', 'product_id'];
public function warehouse_from()
{
retrun $this->belongsTo(Warehouse::class);
}
public function warehouse_to()
{
return $this->belongsTo(Warehouse::class);
}
public function product()
{
return $this->belongsTo(Product::class);
}
}
class Warehouse {
protected $table = 'WAREHOUSE';
protected $fillable = ['name'];
}
So you need to do something like this:
$warehouseFrom = Warehouse::find(1);
$warehouseTo = Warehouse::find(2);
$product = Product::find(23);
$product->transfer($warehouseFrom->id, $warehouseTo->id);

Resources