I have a problem updating a field in my User Model.
I have a field for activating a public_profile defined as boolean:
...
$table->boolean('public_profile')->default(false);
...
in the Model itself i define.
protected $fillable = [..., 'public_profile', ...];
Now i try to update the field via axios depending on the status of an checkbox.
$('#change_public_profile').change(function () {
message={
_token: $('meta[name="csrf-token"]').attr('content'),
public_profile: $('#change_public_profile').is(':checked')
}
axios.post('SOME URL', message).....
Now in my controller i read the request:
$public_profile = $request->input('public_profile');
And call the function:
Auth::user()->togglePublicProfile($public_profile);
In the User Model I have the function:
public function togglePublicProfile($toggleTo){
$user = $this;
$user->public_profile = $toggleTo;
return $user->save();
}
I also tried with boolval() as Mutator, but it never changed.
I do the same to chagne a string value, and there it works well.
Where is my mistake?
Since you have boolean (true/false) you dont need to get any input ($toggleTo) because you only have two states. Each time you call this option you can set the opposite value.
$this->public_profile = !$this->public_profile;
$this->save();
Related
I'm trying to give my modal a custom id (no auto increment). So I've overwrite the boot method of my modal. The creating event is used like this:
public static function boot()
{
static::creating(function ($modal) {
$modal->id = $myID;
return true;
});
}
Now when I try to revert the id after saving an entry the id of the new entry is alwas 0.
$modal = new Modal;
$modal->myValue = $myValue;
$modal->save();
dd($modal->id) // This will returns always 0
The strange thing is that the record is successful written to the database with the right id.
What is wrong with my code?
Edit:
It's not returning null. It's returning 0
You need to disable auto increment with setting property $incrementing to false in your model.
public $incrementing = false
Suppose I have a Course model like this :
class Course extends Model
{
public $primaryKey = 'course_id';
protected $appends = ['teacher_name'];
public function getTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
}
public function teacher ()
{
return $this->belongsTo('App\User', 'teacher', 'user_id');
}
}
And in the other hand there is a User model like this :
class User extends Authenticatable
{
public $primaryKey = 'user_id';
protected $appends = ['full_name'];
public function getFullNameAttribute ()
{
return $this->name . ' ' . $this->family;
}
public function course ()
{
return $this->hasMany('App\Course', 'teacher', 'user_id');
}
}
As you can see there is a hasMany relationship between those.
There is an full_name accessor in User model.
Now I want to add a teacher_name accessor to Course model that uses it's teacher relations and gets full_name of teacher and appends to Course always.
In fact I want whenever call a Course model, it's related teacher name included like other properties.
But every time , when call a Course model , I got this error :
exception 'ErrorException' with message 'Trying to get property of non-object' in D:\wamp\www\lms-api\app\Course.php:166
That refers to this line of Course model :
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
I do not know how can I solve that and what is problem exactly.
Yikes some interesting answers here.
FYI to those coming after me- getFooAttribute() should return the data, and not modify the internal attributes array.
If you set a new value in the attributes array (that doesnt exist in this model's db schema) and then attempt to save the model, you'll hit a query exception.
It's worth reading up the laravel docs on attribute accessors/mutators for more info.
Furthermore, if you need to access a related object from within the model (like in an accessor) you ought to call $related = $this->getRelation('foo'); - note that if the relation isnt loaded (e.g., if you didnt fetch this object/collection with eager loaded relations) then $this->getRelation() could return null, but crucially if it is loaded, it won't run the same query(ies) to fetch the data again. So couple that with if (!$this->relationLoaded('foo')) { $this->loadRelation('foo'); }. You can then interact with the related object/collection as normal.
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
Should be
$this->attributes['teacher_name'] = $this->teacher->full_name;
First thing is that you want to reference the relationship, so loose the brackets (), and because the relationship is belongsTo, you will have one user / teacher returned. So you don't need the first().
We haven't seen your fields but probably you will have to change:
return $this->belongsTo('App\User', 'teacher', 'user_id');
to
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
where foreign_key and other_key are the primary keys that you need to make the join on.
Check this link from the documentation for reference:
https://laravel.com/docs/5.4/eloquent-relationships#one-to-many-inverse
the right way to do this is:
COURSE
public function setTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher->full_name;
}
100% working for me.
I have one to one relationship between Order and Shipment. I have to add the accessor of shipments table column from orders table.
function getOrderNoAttribute()
{
$appendText = "OR100";
if($this->orderShipment()->first()) {
$appendText = $this->orderShipment()->first()->is_shipping === 1 ? "ORE100" : "OR100";
}
return $appendText . $this->attributes['id'];
}
This error is only object data to array use or array data to object data use.
example::
$var->feild insted of $var[feild]
$var[feild] insted of $var->feild
You should use return for accessors . something like this :
public function getTeacherNameAttribute ()
{
return $this->teacher()->first()->full_name ?? '';
}
maybe a course hasn't teacher.
I'm trying to update a row in a particular table, laravel does not shows any error but value is not updating in database.
this is my update method code:
function update(Request $request){
$product=product::find($request['Id']);
$product->productName=$request['name'];
$product->description=$request['desc'];
$product->discount=$request['discount'];
$product->inventory=$request['inventory'];
$product->save();
return response()->json(['message'=>$product->productName],200);
}
I'm successfully getting all the data and I've checked that my changing the value of response json
the variable $product->productName also shows updated value as it is present after save() method but nothing changes in database.
The problem is with this piece of code as I have checked my model i.e product and its working fine as $product has value.
By default Laravel is protecting all models from mass-assignment vulnerability. So you have to specify either a $fillable (which fields can be modified) or $guarded (which fields can not be modified) property.
In your case add this to the model:
protected $fillable = [
'productName',
'description',
'discount',
'inventory',
];
Are you not trying to update this record?
Why are you using save() method, why not use update() since you are trying to set the given product with new set of values?:
$product->update();
So you can finally have (suggesting a check on if a product exists and if the update was successful - you can disregard it if you like):
function update(Request $request)
{
if(!$product=product::find($request['Id']))
{
return response()->json('Product does not exist', 404);
}
$product->productName=$request['name'];
$product->description=$request['desc'];
$product->discount=$request['discount'];
$product->inventory=$request['inventory'];
if($product->update())
{
return response()->json(['message'=>$product->productName],200);
}
return response()->json('Something went wrong', 500);
}
Hope it helps :)
Suppose I have a Post model by this Attributes :
post_id
title
description
owner //=> type same as user_id of User Model
created_at
updated_at
And now I want to fill out owner field with current (Authenticated) user ID on store action of PostConroller when using Create Model. (owner value not included in $dataArray and should automatically get user_id):
Post::create($dataArray)
Is there a way to do that?
In your model class, add save function override:
public function save(array $options = array())
{
$this->owner = auth()->id();
parent::save($options);
}
That's automatic. Just be carefull if you tend to use save in any other scenario so you don't overwrite owner.
I'm not sure what do you mean by automatically, but you can add user_id to an array:
$dataArray['owner'] = $user_id;
Post::create($dataArray);
But usually you're using collections when creating new model, so:
$dataCollection->put('owner', $user_id);
Post::create($dataCollection);
will add user_id to collection.
Also, do not forget to add owner to $fillable array.
public function save(array $options = []) {
if (!isset($this->user_id) || !(intval($this->user_id)>0) ) {
$this->user_id = auth()->id();
}
return parent::save($options);
}
If your user->id's are number
Remember the return, else save is always false
I#m stuck on this too.
Automatic means that you can provide ALL other data, but when a create is called, the model just knows to add user to equal Auth:id()
like this? (but this isn't working for me
protected static function booting(): void
{
static::creating(function ($product) {
$product->user_id = Auth::id();
});
}
I am loading some data into an Eloquent model via an appended attribute and the returned model's attribute is always null. I have protected $appends = array('survey_status); defined in my model (named Survey), and have the accessor defined as such:
public function getSurveyStatusAttribute($value){
return $value;
}
I have tried setting the attribute both as a property and in bracket notation($this->survey_status = ... & $this->attributes['survey_status'] = ..) and also tried using the setAppends() method prior to returning the model, all to no avail.
This was reported on the Laravel forums back at the end of Sept. 2013 and reported as fixed that Oct. (see: https://github.com/laravel/framework/issues/2336 and http://laravel.io/forum/02-26-2014-model-attribute-accessor-not-working-with-object-get-helper-function)
I am on the most current version of Laravel 4 (v4.2.17) which was released in Feb of this year. And from what I read in the docs and elsewhere it seems as though I'm doing everything correctly. Can any see something I'm not doing or confirm this is still an issue?
UPDATE
So I think I figured out 75% of my issue. I didn't realize you could pass an array to $model->load() to make complex queries using where/orWhere/etc. So this basic example works:
$survey = Survey::find(168);
$survey->load(array('surveyStatus' => function ($q){
$q->where('organization_id', '=', 7485);
}));
return Response::json($survey);
In the response my SurveyStatus model is supplied. My issue now is I am trying to iterate of a collection of Survey models to add a SurveyStatus relation just like the working one above but the attribute isn't there on the response. This is what I'm using to iterate the collection:
$org->surveySets->each(function ($ss) use ($id){
$fye = $ss->fiscal_year_end;
$ss->surveys->each(function ($survey) use ($id, $fye){
$sid = $survey->id;
$survey->load(array('surveyStatus' => function ($q) use($id, $fye){
$q->where('organization_id', '=', $id)->where('fiscal_year_end', '=', $fye);
}));
$survey->content_groups->each(function ($cg) use ($id, $sid, $fye){
$cg->content_rows->each(function ($cr) use ($id, $sid, $fye){
$cr->questions->each(function ($q) use ($id, $sid, $fye){
// do the same thing as surveyStatus but load surveyData relation into question
});
});
});
});
});
Is there some reason the loading doesn't 'stick' when iterating over a collection?
Correct me if I'm wrong, but appends doesn't get passed a $value because it's not mapped to a table column. I always thought of it as a computed property of sorts.
Given we have fillable columns 'first' and 'last' we might create an appends called 'fullname'.
protected $appends = [
'fullname'
];
public function getFullnameAttribute()
{
return $this->attributes['fullname'] = $this->first . ' ' . $this->last;
}
Essentially what I think your confusing is that appends is extra data that your appending to your model attributes. You are expected to return a value from the accessor. Returning $value will be null because $value doesn't exist, which is why your manually appending it. Try returning 'foo' in your accessor then you'll see what I mean.
Hello if you want to append some extra data related to another model you could do something like this.
protected $appends = [
'catName'
];
// relation
public function category()
{
return $this->hasOne(PostCat::class, 'id', 'id_cat');
}
//getters
public function getCatNameAttribute()
{
return $this->category()->getEager()->first()->name;
}
If your related model hold many db row considere this
protected $with = [
'category'
];
protected $appends = [
'catName'
];
// relation
public function category()
{
return $this->hasOne(PostCat::class, 'id', 'id_cat');
}
//getters
public function getCatNameAttribute()
{
return $this->category->name;
}
best regards