show related table columns in all select of model laravel - laravel

I want show related table columns (customers.name) in all select of model (User) laravel.
I use accessor laravel.
user table:
id name customer_id
1 hassan 1
customer table:
id name
1 customer1
now use
$user = Auth::user();
return $user;
I want show:
id: 1,
name: "hassan",
customer_id: {
id: 1,
name: "customer1"
}
but show this error:
Failed calling App\User::jsonSerialize()
class User extends Authenticatable
{
use EntrustUserTrait;
/**
* Get the user's customer name.
*
* #param string $value
* #return array
*/
public function getCustomerIdAttribute($value)
{
return [
'id' => $value,
'name' => $this->customer->name
];
}
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'customer_id' => 'array',
];
/**
* Get the customer record associated with the user.
*/
public function customer()
{
return $this->belongsTo(Customer::class);
}
}

So, you want to get customer name from users table based on customer_id in users.
In User.php model
public function customer(){
return $this->hasOne(Customer::class,'id','customer_id');
}
Then,
$user = Auth::user();
$user->customer;

Seems like this is a known issue (https://github.com/FrozenNode/Laravel-Administrator/issues/879).
I would suggest, after getting your ::all() result, you loop through it and call $user->customer.
foreach($result as $user) $user->customer;

You should remove the $casts property. There is no way an integer can be converted to an array directly from the database, as the casts property is immediately used when selecting attributes from the database.
Also, there is no need for the getCustomerIdAttribute method, as the customer will be automatically be converted to a fictive attribute called 'customer'.
In short: just defining the customer relationship is enough. It should return the requested output except for it being called 'customer' instead of 'customer_id'.

I find answer.
public function getCustomerNameAttribute()
{
return $this->attributes['customer_name'] = ($this->customer ? $this->customer->name : null);
}
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
'customer_name',
];

Related

Eloquent relationship returning all when ID doesn't match

For some reason my relationship is fetching all from the corresponding table when I dump it, however dumping the result does not show these rows.
The slider ID does not match the slider_id within the settings table.
So the following works fine, as expected the settings is an empty array:
/**
* #return HasOne
*/
public function slider(): HasOne
{
return $this->hasOne(Slider::class)->withDefault(
(new Slider())->attributesToArray()
);
}
Result:
{
"name": "media-slider",
"settings": []
}
However when I dump within the attribute I get all the rows from the settings table, when this query should be getting all settings where the slider_id matches the current slider, which has a different ID.
<?php
namespace App\Models\Media;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
class Slider extends Model
{
/** #var string[] */
protected $appends = [ 'settings' ];
protected $defaults = [
'test' => [
'id' => 0,
'name' => 'default name',
]
];
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
$this->attributes = $this->defaults['test'];
}
/**
* #return HasMany
*/
public function settings(): HasMany
{
return $this->hasMany(SliderSetting::class);
}
/**
* Get the slider settings, extract the value and key by the key, also
* group if multiple setting groups are required.
*
* Perform this logic here so data can be used directly by the JavaScript.
*
* #return \Illuminate\Database\Eloquent\Collection|Collection
*/
public function getSettingsAttribute()
{
dd($this->settings()->get()); // This should be empty!
return $this->settings()->get()
->groupBy('group')
->map(static function ($group) {
$group = $group->keyBy('key');
return $group->map(static function ($setting) {
return $setting->getAttribute('value');
});
});
}
}
Edit
/**
* #return HasMany
*/
public function sliderSettings(): HasMany
{
dd($this->hasMany(SliderSetting::class)->toSql());
return $this->hasMany(SliderSetting::class);
}
The above outputs:
select * from slider_settings
Shouldn't it be the following?
select * from slider_settings where slider_settings.slider_id = ?

Laravel Relationship Issues : Laravel 5.4

I have 2 tables in my application... Users Conventioners
I have users id in the conventioners table and i want to access their genders from the Users table....
I have like 10 user ids in the conventioners table and 20 users in the users table...
Please how do I access all their genders in the users table...
$conventioners->users()->gender
Conventioners is an instance of the Conventioner Model which contains a relationship **belongsToMany
Thanks alot guys
Here is my Conventioner Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Conventioner extends Model
{
/**
* #var string
*/
protected $table = 'conventioners';
/**
* #var array
*/
protected $fillable = [
'user_id','year','church_id','convention_id'
];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('App\User');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function users()
{
return $this->hasMany('App\User');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function convention()
{
return $this->belongsTo('App\Convention');
}
}
Here is my ConventionController method called Convention...
It retrieves the details for the current convention
public function convention($slug)
{
if(!$this->admin()) return redirect()->back();
$convention = Convention::where('slug', $slug)->first();
$participants = Conventioner::where('convention_id', $convention->id)->get();
$conventioner = [];
foreach($participants as $participant)
{
$thisUser = [];
$thisUser['data'] = User::withTrashed()->where('id', $participant->user_id)->first();
$thisUser['convention'] = $participant;
array_push($conventioner, $thisUser);
}
var_dump($participants->users()->pluck('gender')->all());
return view('dashboard/conventions/convention', [
'convention' => $convention,
'user' => Auth::user(),
'conventioners' => $convention->conventioners(),
'participants' => $conventioner
]);
}
The problem is that users is a collection not an individual that you can call gender on. If you want a list of all the genders you can use the following:
Conventioner::where('convention_id', $convention->id)->with('users')->get()
$conventioners->pluck('users')->pluck('gender')->all();
This will return an array of the genders. You can read more about pluck here.
The pluck method retrieves all of the values for a given key

access to belongsTo method in same model laravel

I use this model but use this model show below error:
Failed calling App\User::jsonSerialize()
but remove "$this->customer->name" result is ok.
thanksssssssssssssssssssssssssssssssssssssssssssssssssssssssssss.
class User extends Authenticatable
{
/**
* Get the user's customer name.
*
* #param string $value
* #return array
*/
public function getCustomerIdAttribute($value)
{
return [
'id' => $value,
'name' => $this->customer->name
];
}
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'customer_id' => 'array',
];
/**
* Get the customer record associated with the user.
*/
public function customer()
{
return $this->belongsTo(Customer::class);
}
}
Your issue is that $this->customer is returning null, which is causing $this->customer->name to cause an error.
When you json_encode a Model, or convert it to a string, or otherwise call toJson on it, it will call the jsonSerialize() method.
At some point, this ends up calling your getCustomerIdAttribute() accessor you have defined. Inside this accessor, you have the statement $this->customer->name. However, if the current model is not related to a customer record, then $this->customer will return null, and then $this->customer->name will cause an error. When $this->customer->name causes an error, it causes jsonSerialize() to fail.
In your accessor, just make sure to check if $this->customer is valid before attempting to access the name attribute:
public function getCustomerIdAttribute($value)
{
return [
'id' => $value,
'name' => ($this->customer ? $this->customer->name : null)
];
}

Laravel Model accessing a value of an instance of its self

I've got a model and the model its self could be linked to multiple other databases but only one at a time.
Instead of having a eloquent method for all the possible databases; it could have one that will use a variable from the self instance to choose the database and return just that.
It will save alot of work, as returning each one and testing to see if there are any results is cumbersome.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Feature extends Model
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'companies';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'db_name',
'enabled',
];
/**
* Uses the its own database name to determine which input to return.
*/
public function inputs() {
// if this->hidden->db_name == 'input type 1'
// return $this->HasMany(InputType1::class);
.... and so on
} // end function inputs
}
This is definitely a strange behaviour but I think you can achieve what you are looking for like so :
//in your model
public function inputs()
{
switch ($this->attributes['db_name']) {
case : 'input type 1':
return $this->hasMany(InputType1::class);
case : //some other database name
return //another relation
}
}
Expanding on shempognon answer, what I actually got to work was
switch($this->db_name) {
case 'Input_Timesheet':
return $this->hasMany(Input_type1::class);
}

Eloquent ORM all() not returning anything

Shoot me down if I this is a silly question, but I am really struggling to get this all() function working for me. It is returning empty list for me. Any help will be highly appreciated. I have got 2 rows in the newsletters table
Model looks like this -
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class Newsletters extends Eloquent {
//use UserTrait, RemindableTrait;
use SoftDeletingTrait; // <-- Use This Insteaf Of protected $softDelete = true;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'newsletters';
/**
* The attributes excluded from the model's JSON form.
*
* #var array */
protected $guarded = array('newsletterId');
protected $fillable = array('name', 'subject','from_email','from_name');
public static $rules = array(
'name' => 'required|min:5',
'subject' => 'required|min:5',
'from_email' => 'required|email',
'from_name' => 'required'
);
}
My call in the controller is like this -
<?php
class newslettersController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//$newsletters = Newsletters::paginate(3);
$newsletters = Newsletters::all();
echo $newsletters;exit();
return View::make('newsletters.index', compact('newsletters'));
}
Any value - even 0000-00-00 00:00:00 - in the deleted_at column tells Laravel that the item has been deleted. Change your default value for that column to NULL or new items will be flagged as deleted on creation.
The $table->softDeletes() Schema function does this automatically if you use it in a migration.
As soon as you use the SoftDeletingTrait a global scope will be applied to every query with your model so all records where deleted_at is not NULL will be ignored.
Illuminate\Database\Eloquent\SoftDeletingScope:
public function apply(Builder $builder)
{
$model = $builder->getModel();
$builder->whereNull($model->getQualifiedDeletedAtColumn()); // <<-- this
$this->extend($builder);
}
Change the default of your deleted_at column to NULL and update the existing records to be NULL as well.
If you are sure newsletters is the correct table name as #Ray said.
Try this:
$newsLetters = DB::table('newsletters')->get();

Resources