Accessor Not Working Even Though Column Exists? - laravel

I have a column in the "products" table called "walkover_only". I can access this attribute easily anywhere with $product->walkover_only, but I can't change it with an accessor?
public function getWalkoverOnlyAttribute($value)
{
if (strpos($this->name, 'Test') !== false) {
return 0;
} else {
return $value;
}
}
I've tried even just return 0 with no if statement, and everything still just returns its normal value. It doesn't need $appends because I can access the value everywhere just fine, it's a real column. I just can't affect what it returns in any way.

Related

Add attribute to Laravel model

I have user model, and I want to add if this user is qualified or not, I have some query to determine that,
User.php
....
public function getIsQualifiedAttribute($value)
{
return $this->qualified()->first() ? true : false;
}
public function scopeQualified($query)
{
return $query->where("years_of_experience",">=",5);
}
and this is how I want to print it
{{$user->is_qualified}}
but I can't make it work, it keeps giving me wrong value.
Laravel accessors does not have parameter
try to change your method like this
public function getIsQualifiedAttribute()
{
return $this->qualified()->first() ? true : false;
}
You don't need to do another query to this same table if you already have the model instance you want to check an attribute for. Just have the accessor check the years_of_experience field of the model:
public function getIsQualifiedAttribute()
{
return $this->years_of_experience >= 5;
}
{{ $user->is_qualified ? 'Y' : 'N' }}
With your current setup you are doing a query to the database to get the first record which has years_of_experience >= 5 every time the accessor was hit. If any record in that table has years_of_experience >= 5 that will return true.

How to make empty values have a default value?

Im trying to give model attribute values another value when they are blank,
At the moment this is what I'm working with in my model:
public function getAttribute($property){
if(blank($this->attributes[$property])){
return $this->attributes[$property] = '-';
}else{
return $this->attributes[$property];
}
}
It works, but I dont think this is the right way to do it.
Im looking for a proper way of doing this.
example:
lets say the value in the database is NULL,
I want it to show "-" when displaying, but I dont want to save "-" in the database.
(I also don't want to use "get...Value" mutators for every value)
Solution 1
Since PHP 7 there is a new feature called the Null Coalescing operator. It returns the first operator when it exists and is not NULL:
{{ $model->attribute ?? '-' }}
Which is the same as this:
{{ isset($model->attribute) ? $model->attribute : '-' }}
Solution 2
Another solution would be a little bit harder, but doable:
Create a base model to which you extend all the other models:
class BaseModel extends Model {
protected $emptyAttributes = [];
protected function getAttribute($property)
{
if (in_array($property, $this->emptyAttributes) && blank($this->attributes[$property])) {
return '-';
}
else {
return $this->attributes[$property];
}
}
}
Now extend all the models you want to this new class and create an array of 'attributes to replace':
class User extends BaseModel {
protected $emptyAttributes = ['name', 'email'];
}
This should automatically replace the attributes name and email when they are empty, NULL or a string of only spaces.
Side note:
You could also move the functionality to a trait (which could be a more elegant solution, but that's up to you).

Laravel 5.2: Accessor on a column with camel case in its name

Im trying to use a laravel accessor to modify the content of a column when retrieving it. Im doing it like this:
On my model:
public function getMyColumnAttribute($value)
{
//Modify the content
return $value.'tttt';
}
On my controller:
public function test()
{
return MyModel::select('my_column')->find(1);
}
This works perfectly when the column in my DB is named 'my_column', but my entire database use camel case, so the actual name of the column is myColumn and the accessor just dont work in that case, I mean, it does return the value of my column, but without the modification I did in the accessor. I think it must be a way to it but I cant find how.
Thanks for the help
EDIT
I just realized that while this doesnt work: (myColumn is of type time on a MySql DB)
public function test()
{
return MyColumn::select('myColumn')->find(1);
//returns {"myColumn":"08:00:00"}
}
This acctually do what I expect
public function test()
{
$result = MyColumn::select('myColumn')->find(1);
return $result->myColumn;
// returns 08:00:00tttt
}
accessor doesnt modify the column raw data, it is used on create a new Attribute
use Mutator, save the modifyed raw data to db
use Accessor, get the raw data and modify it and assign to a new attribute
in your case
public function getMyColumnAttribute()
{
//Modify the content
return $this->attributes['type_column_name_here'] . 'tttt';
}
public function test()
{
// myColumn = the column name
$result = MyColumn::select('myColumn')->find(1);
// this is return the column value 08:00:00
return $result->myColumn;
// this will return accessor value 08:00:00tttt
return $result->my_column;
}
getMyColumnAttribute will convert to my_column

Laravel how to get object after and before saving this?

I'm using Laravel 4.2
My model has a function like this:
ServiceLog::saved(function($servicelog) {
if($servicelog->date_created != $old_date_created) {
//do something here
}
});
I want to compare the value of the field date_created after and before saving $servicelog
How do I get the $old_date_created ?
You have the getDirty() and isDirty() methods according to the documentation. isDirty checks if given attribute has changed and getDirty returns the attributes, that have been changed. You also have getOriginal() method, which will return the previous value of given attribute (before the change).
What you can do is this:
ServiceLog::saving(function($model)
{
// Check if property has changed
if ($model->isDirty('date_created')) {
// Get the original value before the change
$oldDate = $model->getOriginal('date_created');
// Get current value for date_changed
$newDate = $model->date_created;
echo "The date_created changed from $oldDate to $newDate";
}
return true; //if false the model won't save!
});

Save and Update in a controller together in Yii

There are two tables in my db, users and profile. Profile has user_id as a primary key. Every user can have only one profile. When I upload a image file its name is stored in profile table with that user_id. When there are other fields to be updated in profile table, I first check whether there is already a record with that user_id. In my Profile model I have written
public function checkForSaveOrUpdate()
{
return self::model()->findByAttributes(array('user_id'=>Yii::app()->user->id));
}
and my controller file looks something like this
public function actionCreateInfo()
{
$profile = new Profile;
$profile->user_id = Yii::app()->user->id;
if(isset($_POST['Profile']))
{
if($profile->checkForSaveOrUpdate() === null)
{
$profile->attributes = $_POST['Profile'];
if($profile->save())
Yii::app()->user->setFlash('success','Profile has been saved successfully');
}
elseif($profile = $profile->checkForSaveOrUpdate())
{
$profile->attributes = $_POST['Profile'];
if($profile->update())
Yii::app()->user->setFlash('success','Profile has been updated successfully');
}
$this->redirect(array('index'));
}
$this->render('createInfo',array('profile'=>$profile));
}
My problem is when I already have a record in database,in profile, and I submit a new form the old data is all deleted and only the current values submitted are updated, whereas it should keep the old values and only update the new ones.
If you instaciate the model like:
$model = new YourModel;
you will have the $model->isNewRecord set to true:
var_dump($model->isNewRecord); // true, in this case you use $model->save()
When you find a record, the same property will have the opposite value:
$model = YourModel::model()->findByPk(1);
var_dump($model->isNewRecord); // false - and now you use $model->update(), instead.
Change your function to static function
public static function checkForSaveOrUpdate()
{
return self::model()->findByAttributes(array('user_id'=>Yii::app()->user->id));
}
Then modify action as
public function actionCreateInfo()
{
$profile = Profile::checkForSaveOrUpdate();
if($profile===null)
{
$profile=new Profile;
$profile->user_id = Yii::app()->user->id;
}
if(isset($_POST['Profile']))
{
$profile->attributes = $_POST['Profile'];
if($profile->save())
Yii::app()->user->setFlash('success','Profile has been saved successfully');
$this->redirect(array('index'));
}
$this->render('createInfo',array('profile'=>$profile));
}
Your POST data probably includes all model attributes, including those left blank by the user set to the empty string; the empty string is an accepted value for massive assignment unless otherwise stated in the model rules; a massive assignment is what you actually do with $profile->attributes = $_POST['Profile'];.
One solution would be to unset those attributes that you don't want to update, e.g. those containing an empty string, in the controller.
But this kind of rule should be defined in the model and triggered by calling the validate() method, which you are now skipping by calling update(). You better call save() because internally calls validate() as opposed to update().
A rule for a default value is defined like this:
array(
'attr_name',
'default',
'setOnEmpty' => true,
'value' => null
)

Resources