Laravel how to get object after and before saving this? - laravel

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!
});

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.

Accessor Not Working Even Though Column Exists?

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.

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 Has One Relation changing the identifier value

I'm not sure this is a real relation. I will try to explain the best way I can.
So first of all, I have three models :
Appartement,
AppartementPrice
The AppartementPrice depends on :
- appartement_id
I would like the AppartementPrice to be retrieve like that :
If there is a specific price for the appartement, then retrieve it, If not retrieve the price for all appartement which is stored in the database with an appartement_id = 0.
So basically what I would like is to do something like that :
public function price()
{
if(isset($this->hasOne('AppartementPrice')->price) // Check that relation exists
return $this->hasOne('AppartementPrice');
else
return $this->hasOne('AppartementPrice')->where('appartement_id', '0');
}
But this is not working.
It does not retrive me the default price.
I guess anyway this is not a best practice ?
I first tried to get the informations like that :
//Check if appartment has a specific price or retrieve default
if($priceAppartement = AppartementPrice::getPriceByCompanyAppartement($this->id))
return $priceAppartement;
else
return AppartementPrice::getDefaultPrice();
But I had this error :
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
when doing :
echo $app->price->price;
How can I check that a relation exists ? And is there a way to do as I describe ?
Thank you
You can't replace relation like this, as what you intend is not logical - you want to retrieve relation that doesn't exist.
Instead you can do this:
public function getPriceAttribute()
{
return ($this->priceRelation) ?: $this->priceDefault();
}
public function priceDefault()
{
// edit: let's cache this one so you don't call the query everytime
// you want the price
return AppartmentPrice::remember(5)->find(0);
}
public function priceRelation()
{
return $this->hasOne('AppartementPrice');
}
Then you achieve what you wanted:
$app->price; // returns AppartmentPrice object related or default one
HOWEVER mind that you won't be able to work on the relation like normally:
$price = new AppartmentPrice([...]);
$app->price()->save($price); // will not work, instead use:
$app->priceRelation()->save($price);
First of all something really important in Laravel 4.
When you do not use parentheses when querying relationship it means you want to retreive a Collention of your Model.
You have to use parentheses if you want to continue your query.
Ex:
// for getting prices collection (if not hasOne). (look like AppartementPrice)
$appartment->price;
// for getting the query which will ask the DB to get all
//price attached to this appartment, and then you can continue querying
$priceQuery = $appartment->price();
// Or you can chain your query
$appartment->price()->where('price', '>', 0)->get() // or first() or count();
Secondly, your question.
//Appartement Model
// This function is needed to keep querying the DB
public function price()
{
return $this->hasOne('AppartementPrice')
}
// This one is for getting the appartment price, like you want to
public function getAppartmentPrice()
{
$price_object = $this->price;
if (!$price_object) // Appartment does not have any price {
return AppartementPrice->where('appartement_id', '=', 0)->get();
}
return $price_object;
}

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