In my Eloquent Model I have added a class attribute:
/**
* #return bool
*/
public function getIsViewable()
{
return $this->isViewable;
}
This attribute is not saved in the database as it is just a computed value.
In my controller I have an Eloquent Collection of this object which I convert to an array:
$images = $query->get();
$images = $images->toArray();
How can I add the class attribute property to each image item in the array?
Method should be named getMyVariableAttribute ie. getIsViewableAttribute
On the model add the following protected $appends = ['is_viewable'] in order to get the computed property when serializing.
Your method name is missing the Attribute part. Rename getIsViewable() to getIsViewableAttribute()
/**
* #return bool
*/
public function getIsViewableAttribute()
{
return $this->isViewable;
}
https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor
Related
I have custom model User and I want push custom attribute to model after fetching data. How I can do it?
I know what before fetching we can add custom attibute like this:
class User extends Model
{
protected $appends = ['callable'];
public function getCallableAttribute()
{
$callable = $this->getMeta('phone') ? true : false;
return $callable;
}
}
But how do it after fetching data, for example after:
$user = User::find(1);
And now how append custom attribute to fetched User object data?
You can define a Laravel Accessor for that
E.g.
class User extends Model
{
/**
* Get the user's first name.
*
* #param string $value
* #return string
*/
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
/**
* Get the user's full name.
*
* #return string
*/
public function getFullNameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
}
Then you can access Accessors like this:
$user = App\User::find(1);
$firstName = $user->first_name; // In studly Case
$firstName = $user->full_name; // In studly Case
You can read more about Laravel Accessors here: https://laravel.com/docs/5.8/eloquent-mutators#defining-an-accessor
I want to hide some data which selected from database but reinitialize from some method in Controller not defined in its Models.
function ddd(){
return Client::select($this->_client)->with([
'Contact'=>function($s){
//$this->setHidden('use_id');
//$s->setHidden('use_id');
$s->select($this->_contact);
},
'Employer'=>function($s){$s->select($this->_employers);},
])->get();
}
You requirement is not very clear. However. I am assuming that you have 3 models Client hasOne Contact and belongsTo Employer.
In order to hide the use_id property of the Client model you can define a hidden property in your model
class Client extends Model
{
//will hide the `use_id` from the model's array and json representation.
protected $hidden = ['use_id'];
//Relations
/**
* Get the Contact which the given Client has.
* #return \Illuminate\Database\Eloquent\Relations\HasOne
* will return a App\Contact model
*/
public function contact()
{
return $this->hasOne('App\Contact');
}
/**
* Get the Employee to which the given Client belongs.
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
* will return a App\Employer model
*/
public function employer()
{
return $this->belongsTo('App\Employer');
}
}
Then in probably your ClientsController in some action ddd
public function ddd()
{
return Client::with('contact')->with('employer')->get();
}
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);
}
I know you can hide an entire pivot table as such
protected $hidden = ['pivot'];
How do you hide a specific field within pivot table, like
protected $hidden = ['pivot.created_at'];
The above does not work from what I've tested
After so much trying and looking into source of Laravel Model, i finally got it achieved.
Please put following method at your Model.
/**
* Convert the model instance to an array.
*
* #return array
*/
public function toArray()
{
$attributes = $this->attributesToArray();
$attributes = array_merge($attributes, $this->relationsToArray());
unset($attributes['pivot']['created_at']);
return $attributes;
}
This solves the purpose.
I am having an issue with laravel not seeing my tags() method for attaching new tags on a new entry. I keep getting Call to a member function on a non-object when I try to run the method and attach tags to my Tile model. All methods are returning their relations. I followed the same order as the documentation says eloquent.
Controller
$tile = \Tiles\Tile::find($tile_id);
$tile->tags()->attach($tag_array);
Model
<?php namespace Tiles;
use Illuminate\Database\Eloquent\Model;
class Tile extends Model {
/**
* The Tile table
* #var string
*/
protected $table = 'tiles';
/**
* Pivot table for tags
* #var string
*/
protected $pivot = 'tag_tile';
/**
* Get the tags associated with the given tile
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags() {
return $this->belongsToMany('Tiles\Tag', $this->pivot, 'tile_id', 'tag_id')->withTimestamps();
}
}
Try it
Model
public function tags() {
return $this->belongsToMany('Tiles\Tag', $this->pivot, 'tag_id', 'tile_id')->withTimestamps();
}
Thanks for all your help. I figured out the solution. I created a method in my model and pushed each to an array and fed it to the attach method. It works now.