In my User model, I have an appends fields:
protected $appends = [
'is_admin'
];
It will appends is_admin field in every request by using with() eager loading. However, in some scenario I don't want to return is_admin field, I am trying to use the follows:
$this->belongsTo('App\Models\User')
->select(['id', 'username', 'first_name', 'last_name']);
But it doesn't work.
Is the appends field always be appended even I use custome select field ?
appends is used when the model is serialized; it 'appends' attributes to the output.
If you have a single model and you want to not have the appends accessors added to the serialized data, you can set them hidden.
Example:
$test = new class extends Illuminate\Database\Eloquent\Model {
protected $appends = ['is_admin'];
public function getIsAdminAttribute() {
return rand(0, 1);
}
};
dump($test->toArray()); // will contain 'is_admin'
$test->makeHidden('is_admin');
dump($test->toArray()); // will not contain 'is_admin'
// This can be applied to Eloquent Collections.
$model->relation->makeHidden('is_admin');
One way of doing it.
Simply put this result to a variable
$data = $this->belongsTo('App\Models\User')->select(['id', 'username', 'first_name', 'last_name']);
and use directly
$data->makeHidden("is_admin");
This will work for you
Related
I am trying to retrieve and paginate the related User models of a Group model.
The response should only contain first_name, but there seems to be two issues causing additional fields to get added.
Because an 'appends' is defined it seems to be bringing in those fields as well even though I have a select statement.
When I use the paginate() function it seems to omit my select statement altogether and brings in all fields. When I use get() instead, I at least get first_name + the appends.
Questions:
How do you disable appends for a single query?
Why isn't the select statement working when paginating results of the belongsToMany relationship? Why would all fields be returned instead of the ones passed to select()?
I simplified/changed the code to show what I'm trying to do.
Group Model
protected $fillable = [
'name',
]
public function users()
{
return $this->belongsToMany('App\Models\User');
}
User Model
protected $fillable = [
'first_name',
'... many more fields....'
]
public $appends = [
'profile_pic'
];
Controller:
$users = $group->users();
// returns all fillable and appends fields instead of just first_name
$paginated = $users->select('first_name')->paginate(10);
Thank you!
I have a laravel table with a column I've defined like this in the migration:
$table->json('json');
And in the model, I cast it to an array:
protected $casts = [
'json' => 'array'
];
This works perfectly the majority of the time I need it, but there's one api call I'm making where I actually want my collection of that Model to give me the raw string rather than casting it to the array.
So, assuming my model is called Model, my api call looks like this:
$systemModels = Model::whereNull('user_id')->get();
$userModels = Model::where('user_id', $user->id)->get();
return response()->json([
'user_models' => $userModels->toArray(),
'system_models' => $systemModels->toArray()
]);
This is where I'd like the 'json' column of my Model to be rendered as a string rather than cast to an array. Is there a reliable way to do that?
Inside your model you can define a custom attribute which is added when the model is serialized:
class YourModel extends Model
{
protected $appends = ['json_raw'];
public function getJsonRawAttribute()
{
return $this->attributes['json'];
// or return json_encode($this->attributes['json']);
}
}
And then when doing the toArray() you can do $userModels->makeHidden('json')->toArray(); to remove the casted field you do not want.
Let's say I have an endpoint for user submitted forms. The form input will be stored as a JSON object in a column of a database table, and the user ID will be stored in another. Because I don't want users to be able to somehow set any user ID they want, I've left the user_id column out of the $fillable variable of the Eloquent model.
The create() method accepts an array of key/value pairs to be assigned, but will only assign values to fillable columns. How do I add the user's ID to the guarded user_id column at the same time? Do I have to fetch the last row and update the user ID as a second operation?
Thanks for all help, it's much appreciated.
IF you don't have attribute in $fillable it doesn't mean you cannot fill it.
The $fillable property holds the attributes that could be filled using create() or fill() method but you can still set value for any attributes using property access.
So let's assume you have Model with email, something and else properties. You set $fillable like so:
protected $fillable = ['email', 'something'];
Now let's assume you have data like this:
$data = [
'email' => 'sample#example.com',
'something' => 'foo',
'else' => 'bar',
];
so now when you use:
Model::create($data);
you will have filled only email and something because those are in $fillable and else won't be filled because it's not, but you can always do something like this:
$model = new Model($data);
$model->else = 'bar';
$model->save();
so you can set here else property value even if it's not inside $fillable but you need to access it like normal property.
I am trying to find an easier approach to this simple function I have. Basically what I am doing is dynamically loaded a form that's based on an Eloquent model. I do not want to include certain columns in the model like id's and the created_at and update_at columns. I am able to accomplish this with the following piece of code:
get Controller:
$cms_information = collect(CmsUserInformation::where('users_id', Auth::user()->id)->first()->toArray());
$cms_information->forget('id');
$cms_information->forget('users_id');
$cms_information->forget('created_at');
$cms_information->forget('updated_at');
$cms_information->all();
return view('cms::admin.profile', ['user' => Auth::user(), 'cms_information' => $cms_information]);
Then, I will loop through the fields in a form and post them like so:
Post Controller:
$profile = CmsUserInformation::where('users_id', Auth::user()->id)->first();
$cms_user_information = Input::except('_token', 'email', 'password');
foreach($cms_user_information as $field => $info ) {
$profile->$field = $info;
}
$profile->save();
My Eloquent table:
id
user_id
first_name
last_name
email
created_at
updated_at
This works exactly how I want but I feel like it's a quick and dirty way around using the Eloquent object to accomplish this. Does anyone have a way to accomplish this same thing but only use Eloquent object rather than converting to an array and using the collect() function?
You can use the $hidden property on your Eloquent model:
class CmsUserInformation extends Model
{
protected $hidden = [
'id',
'users_id',
'created_at',
'updated_at',
];
}
This will automatically exclude the given attributes when the models are ultimately serialized.
If you only want to hide it in a specific instance, use the setHidden method:
$info = CmsUserInformation::where('users_id', Auth::id())->first();
$info->setHidden([
'id',
'users_id',
'created_at',
'updated_at',
]);
Use hidden property in the model you are using like this:
class User extends Model{
protected $hidden=[
'id',
'created_at',
'updated_at'
];
...
}
I get a very unhelpful error when I try and insert a new record in to my db. Does anyone have any idea where to start to solve this error?
user_id
That's all it says. (This is the name of one of my required fields in the table I'm saving to but it's not very descriptive.)
For reference here's my code:
$data = array(
'user_id'=>1,
'post_type'=>'0',
'post_title'=>'blah',
'description'=>'blah');
//it fails on this line
$id = Post::create($data);
Here's what my model looks like:
class Post extends Eloquent{
public static $rules = array(
'user_id'=>'required',
'post_type'=>'required',
'post_title' => 'required|max:25',
'description'=>'required'
);
public static function validate($data){
return Validator::make($data, static::$rules);
}
public function user(){
return $this->hasOne('User', 'id', 'user_id');
}
}
Tried getting rid of all relationships and validation in the model. That didn't work.
This is called mass-assignment in Laravel, what you need to do to get it working on your model is to set a protected array called $guarded to be empty. Add this to your model.
protected $guarded = array();
What this array does, it can prevent attributes to be mass-assigned with an array, if you don't want an attribute to be filled with the Model::create() method, then you need to specify that attribute in the $guarded array.
If instead you want to specify only the fillable attributes, Laravel's Eloquent also provides an array called $fillable where you specify only the attributes that you want to fill via the mass-assigment way.
Further reading:
Mass Assignment:
http://laravel.com/docs/eloquent#mass-assignment
Create Method:
http://laravel.com/docs/eloquent#insert-update-delete