In my model I have:
//UserAddress.php
protected $with = ['address'];
public function address()
{
return $this->morphOne('App\Address', 'addressable');
}
//User.php
public function userAddress()
{
return $this->hasOne(UserAddress::class);
}
//Address.php
public function addressable()
{
return $this->morphTo();
}
But when I call dd(auth()->user()->userAddress)) The address realtionship is not loaded. It is still null.
#attributes: array:4 [
"id" => "1"
"user_id" => "1"
"created_at" => "2018-11-13 10:11:54"
"updated_at" => "2018-11-13 10:11:54"
]
#original: array:4 [
"id" => "1"
"user_id" => "1"
"created_at" => "2018-11-13 10:11:54"
"updated_at" => "2018-11-13 10:11:54"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [
"address" => null
]
#touches: []
+timestamps: true
However, with dd(auth()->user()->userAddress()->get())) the relationship is eager loaded.
What is the problem?
Edit
It is super weird. If I write auth()->user()->userAddress->address I get null (it should not be that). And when I remove protected $with = ['address']; auth()->user()->userAddress->address gets me the correct model.
I have similar issue. It is loading the related models, but under different key.
I got a pivot model called Skillable it has a morphTo relationship to get the related morphed model.
public function morphedModel(): MorphTo
{
return $this->morphTo('skillable');
}
That works fine without eager loading when used like that
echo $skillable->morphedModel->id; // return some id
However when using eager loading, the morphedModel prop is null.
Skillable::with('morphedModel')->get()->first()->morhphedModel; // returns null
Turns out the eager loading is working almost as expected, however the related (morphed) models are loaded under skillable relationship instead.
dump(Skillable::with('morphedModel')->get()->first());
returns
...
#relations: array:2 [▶
"morphedModel" => null
"skillable" => App\Models\Lesson {#2376 ▶
Not sure why though.. something with my relation definition I guess.
I had the same issue with a one-to-one relationship where the id field was a string. Everything worked until I eager-loaded the connecting table (user_address in you case).
In my case I'd forgotten to define public $incrementing = false; in the connecting table, and once I had added this everything worked.
Related
I have some misunderstanding with the UpdateOrInsert helper with the DB
DB::table('table')
->updateOrInsert( );
}
I have a dynamic collection structured like this:
^ Illuminate\Support\Collection {#1534 ▼
#items: array:9 [▼
"it-IT" => array:1 [▶]
"cs-CZ" => array:1 [▶]
"de-DE" => array:1 [▶]
"en-GB" => array:1 [▶]
"en-US" => array:1 [▶]
"es-ES" => array:1 [▶]
"fr-FR" => array:1 [▶]
"ko-KR" => array:1 [▶]
"sk-SK" => array:1 [▶]
]
I would like to use the it-IT array as reference and Update the other languages or Insert a new line if the it-IT string don't exist.
This Collection comes from an array, I transform it in collectio just for use the chunk(); function.
The problem is, after a lot of tries, using in the correct way the UpdateOrInsert.
Cause, I undestand that I need to separe the reference with the rest, so I split the collection in two collection:
$coll = collect($array);
$chunks = $coll->chunk(500);
$refcol = collect($refArr);
$refchunks = $refcol->chunk(500);
foreach ($chunks as $chunk)
{
DB::table('dictionaries')
->updateOrInsert($refchunks->toArray(),$chunk->toArray() );
}
But this is not enought cause when it start to upgrade the data inside the database i get a strange query error:
select exists(select * from `dictionaries` where ((`1` = stringa di riferimento ))) as `exists`
so I think I have to split the collection in all languages collection, but the number and the languages are not always the same.
How can I do a foreach inside the UpdateOrInsert?
I have tried olso to using the Model way
Dictionary Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Dictionary extends Model
{
protected $primaryKey = null;
public $incrementing = false;
public $timestamps = false;
}
But when I perform the save() but if the it-IT string already exist it go in exception.
I tell to my self "Never give up" so I tried a thing like this:
try{
Dictionary::save();
} chatch (\Exception $e){
Dictionary::update();
}
But it save me the string like { 1: 'string in correct column'} and update method doesn't work.
Any way to help me?
I am having strange issue. The resource method always returns null.
Table name
operating_days
Model
class OperatingDay extends Model
{
/**
* #var string[]
*/
protected $fillable = ['day', 'date'];
}
Controller#edit
public function edit(OperatingDay $operatingDay)
{
return view('admin.day.form')->with('operatingDay', $operatingDay)->with('title', __('admin.day.edit_day'));
}
Route
Route::resource('days', 'OperatingDayController')->names([
'index' => 'admin.days.index',
'store' => 'admin.days.store',
'create' => 'admin.days.create',
'show' => 'admin.days.show',
'update' => 'admin.days.update',
'destroy' => 'admin.days.destroy',
'edit' => 'admin.days.edit',
]);
dd var in view
#dd($operatingDay)
App\OperatingDay {#1400 ▼
#fillable: array:2 [▶]
#connection: null
#table: null
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: false
+wasRecentlyCreated: false
#attributes: []
#original: []
#changes: []
#casts: []
#classCastCache: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
#dd($operatingDay->id)
// output null
The problem is that you named your resource days therefore Laravel will try to route it to a model called Day, but your model is called OperatingDay, in order to route days to OperatingDay you can use explicit binding.
From the docs:
To register an explicit binding, use the router's model method to
specify the class for a given parameter. You should define your
explicit model bindings in the boot method of the RouteServiceProvider
class:
public function boot()
{
parent::boot();
Route::model('user', App\User::class);
}
So in your case it would look something like this:
use App\OperatingDay; // or whatever the namespace to your model is
use Illuminate\Support\Facades\Route;
public function boot()
{
parent::boot();
Route::model('day', OperatingDay::class);
}
If you only need this in one route you could also rename the route parameter:
From the docs:
By default, Route::resource will create the route parameters for your
resource routes based on the "singularized" version of the resource
name. You can easily override this on a per resource basis by using
the parameters method. The array passed into the parameters method
should be an associative array of resource names and parameter names:
Route::resource('users', 'AdminUserController')->parameters([
'users' => 'admin_user'
]);
So in your case it would be something like this:
Route::resource('days', 'OperatingDayController')
->names([
'index' => 'admin.days.index',
'store' => 'admin.days.store',
'create' => 'admin.days.create',
'show' => 'admin.days.show',
'update' => 'admin.days.update',
'destroy' => 'admin.days.destroy',
'edit' => 'admin.days.edit',
])
->parameters(['days' => 'operatingDay']);
I am attempting to use multiple tables for my authentication based on a subdomain. Therefore, I am attempting to use Sentinel's setModel function during runtime to set the model instance.
So in my routes file I have some simple logic:
if (Request::getHost() == $url) {
Sentinel::getUserRepository()->setModel('App\Client');
} else {
Sentinel::getUserRepository()->setModel('App\User');
}
The logic being one URL uses one model and the other uses the other model. Now, when I am attempting to load the App\Client by doing a dd(Sentinel::getUserRepository()); I get a return such as:
IlluminateUserRepository {#113 ▼
#hasher: NativeHasher {#114}
#model: "App\Client"
#dispatcher: Dispatcher {#23 ▶}
#dispatcherStatus: true
}
This is great, however, when I call Sentinel::getUser();, I am left with the following output:
EloquentUser {#230 ▼
#table: "users"
#fillable: array:5 [▶]
#hidden: array:1 [▶]
#persistableKey: "user_id"
#persistableRelationship: "persistences"
#loginNames: array:1 [▶]
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:12 [▶]
#original: array:12 [▶]
#casts: []
#dates: []
#dateFormat: null
#appends: []
#events: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#visible: []
#guarded: array:1 [▶]
#permissionsInstance: null
}
This is referring to the App\User model rather than my App\Client model.
I don't understand why, but I can't seem to get functions of Sentinel to look at the model I am trying to reference.
Here is my Client model as a point of reference.
namespace App;
class Client extends \Cartalyst\Sentinel\Users\EloquentUser
{
/**
* The fields for sentinel to authenticate (login)
*
* #var array
*/
protected $loginNames = ['email'];
/**
* The table associated with model.
*
* #var String
*/
protected $table = 'clients';
/**
* Used for mass assignment fields.
*
* #var Array
*/
protected $fillable = ['email', 'password', 'permissions', 'last_login', 'first_name', 'last_name'];
}
I have used this guide from the Github Wiki, however as you can see Im not achieving what I am trying to do.
How can I use this approach of setting the model during runtime and use the correct model with all of sentinels commands?
To anyone who encounters the same issue, i flagged this as an issue in the cartalyst/sentinel repository and some feedback was provided.
The solution is to not only set the user repository but also define the model on the persistence repository:
Sentinel::getUserRepository()->setUsersModel('App\Client');
Sentinel::getPersistenceRepository()->setUsersModel('App\Client');
Through this methods such as Sentinel::getUser() will access the model specified above.
Please see the full response here: https://github.com/cartalyst/sentinel/issues/367
am simply trying to include a new attribute to be available in the json response but for some reason am also getting the object relation as well.
// user model
protected $guarded = ['id'];
protected $appends = ['role_name'];
protected $hidden = ['remember_token', 'password'];
public function getRoleNameAttribute()
{
return $this->role->type;
}
public function role()
{
return $this->belongsTo(Role::class);
}
// role model
public function users()
{
return $this->hasMany(User::class);
}
when i use dd($user); i get
User {#303
#guarded: array:1 [
0 => "id"
]
#appends: array:1 [
0 => "role_name"
]
#hidden: array:2 [
0 => "remember_token"
1 => "password"
]
#connection: null
#table: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:7 [
"name" => "testing"
"email" => "email#asd.com"
"password" => "$2y$10$fogQXhJZm5eoViM38pge1.BmNxY7IFl515zT83.Ks9Uj26kK9T6Im"
"role_id" => "83eee2e0-8939-48f7-9fbc-1c077e2265e5"
"id" => "a181fb4b-b65a-47b4-9c72-21ea15c6c5a6"
"updated_at" => "2017-01-30 20:23:52"
"created_at" => "2017-01-30 20:23:52"
]
#original: array:7 [
"name" => "testing"
"email" => "email#asd.com"
"password" => "$2y$10$fogQXhJZm5eoViM38pge1.BmNxY7IFl515zT83.Ks9Uj26kK9T6Im"
"role_id" => "83eee2e0-8939-48f7-9fbc-1c077e2265e5"
"id" => "a181fb4b-b65a-47b4-9c72-21ea15c6c5a6"
"updated_at" => "2017-01-30 20:23:52"
"created_at" => "2017-01-30 20:23:52"
]
...
}
and with return response()->json(compact('user')); instead i get
user: {
created_at: "2017-01-30 20:26:12"
email:"email#asd.com"
id:"4b83e031-e8c8-4050-963d-446cb383fb14"
name:"testing"
role:{
created_at:"2016-12-29 10:54:02"
id:"83eee2e0-8939-48f7-9fbc-1c077e2265e5"
type:"user"
updated_at:"2016-12-29 10:54:02"
}
role_id:"83eee2e0-8939-48f7-9fbc-1c077e2265e5"
role_name:"user"
updated_at:"2017-01-30 20:26:12"
}
but what i expect is to only have
user: {
created_at: "2017-01-30 20:26:12"
email:"email#asd.com"
id:"4b83e031-e8c8-4050-963d-446cb383fb14"
name:"testing"
role_id:"83eee2e0-8939-48f7-9fbc-1c077e2265e5"
role_name:"user"
updated_at:"2017-01-30 20:26:12"
}
so am not sure if this is the normal behavior or a bug or maybe am missing something ?
Laravel version 5.3.30
The reason why this is happening is the following
public function getRoleNameAttribute()
{
return $this->role->type;
}
The problem here is the when you say $this->role it will automatically attached the relationship to the model. In order to prevent this, you should simply be able to access the method directly, like $this->role().
public function getRoleNameAttribute()
{
return $this->role()->first()->type;
}
I like to use the dd function to debug. This time when I use it to display a list of appointments, I can't see (no clickable arrow) the data in the attributes and original. I get the brackets [ …19] displayed instead, not sure why.
Collection {#3061 ▼
#items: array:548 [▼
0 => Appointment {#821 ▼
#table: "appointments"
#fillable: array:16 [ …16]
#connection: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:19 [ …19]
#original: array:19 [ …19]
#relations: array:2 [ …2]
#hidden: []
#visible: []
#appends: []
#guarded: array:1 [ …1]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
1 => Appointment {#822 ▶}
2 => Appointment {#823 ▶}
3 => Appointment {#824 ▶}
4 => Appointment {#825 ▶}
5 => Appointment {#826 ▶}
6 => Appointment {#827 ▶}
7 => Appointment {#828 ▶}
And later in the list, I can't even see inside an appointment (no arrows):
81 => Appointment {#902 ▶}
82 => Appointment {#903 ▶}
83 => Appointment {#904 ▶}
84 => Appointment {#905 ▶}
85 => Appointment {#906 …23}
86 => Appointment {#907 …23}
87 => Appointment {#908 …23}
88 => Appointment {#909 …23}
89 => Appointment {#910 …23}
90 => Appointment {#911 …23}
But when I use var_dump, my data looks fine :
array(548) {
[0]=>
array(21) {
["id"]=>
int(149)
["appointmenttype_id"]=>
NULL
["appointmentlocationtype_id"]=>
NULL
["appointment_start"]=>
object(Carbon\Carbon)#812 (3) {
["date"]=>
string(26) "2015-12-21 07:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(16) "America/New_York"
}
["appointment_end"]=>
object(Carbon\Carbon)#811 (3) {
["date"]=>
string(26) "2015-12-21 09:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(16) "America/New_York"
}
Anyone else experienced that situation?
This is a not-so-known caveat of returning too large a list of results. Generally, dd() is meant to be a quick overview of the data you are returning, and handles "drill down" well on smaller groups of data. Once you reach a certain number (I forget the exact one, 500 maybe?), that functionality no longer works.
If you absolutely need to see this data before using it in your code somewhere, use a limit() clause before you get() the results, or use dd($example[0]) to see a single results' details. Hope that helps!
Not a bug in dd() just how the underlying Sympony VarDumper is configured.
I believe the line in question is this one which has sets $maxDepth to 20 but I haven't checked this.
Looking at the Laravel Dumper logic there doesn't seem to be anyway to override this from within Laravel.
I've found a way to work around this, although not recommended, if you really want the entire object dumped, add the following code snippet to /bootstrap/autoload.php
if (! function_exists('dd')) {
/**
* Dump the passed variables and end the script.
*
* #param mixed
* #return void
*/
function dd()
{
array_map(function ($x) {
$dumper = 'cli' === PHP_SAPI ? new \Symfony\Component\VarDumper\Dumper\CliDumper() : new \Illuminate\Support\Debug\HtmlDumper();
$cloner = new \Symfony\Component\VarDumper\Cloner\VarCloner();
$cloner->setMaxItems(-1);
$cloner->setMaxString(-1);
$dumper->dump($cloner->cloneVar($x));
}, func_get_args());
die(1);
}
}
This must be added above the line:
require DIR.'/../vendor/autoload.php';
It overrides the laravel dd function and sets 'setMaxItems' and 'setMaxString' on the Symfony VarCloner object before dumping.