Okay so as far as i can understand using $this->id = id will set that your next request will get the row from the database with that id. (if you have followed the cake conventions).
Now i am trying to set a value and have therefore created the following function in my Product model
$this->id = $product_id;
$product = $this->find('first');
$final_amount = $product['Product']['antal'] - $amount;
$this->saveField('Product.antal',$final_amount);
However when i debug it then $product is not equal to the id i set. meaning it just took the first of the database table.
How come? and if this isnt the way to use $this->id what is?
After setting the id, you are supposed to use the read method. it will get the record you desired for.
You should call $this->ModelName->read();
Using the find have nothing to do with setting the id. it will simply find a record based on the options supplied.
Try this:
$this->findById('first', $product_id);
Creating or updating is controlled by the model’s id field. If
$Model->id is set, the record with this primary key is updated.
Otherwise a new record is created [...]
More http://book.cakephp.org/2.0/en/models/saving-your-data.html
Edit:
To update row try this;
$product = $this->findById('first', $product_id);
$final_amount = $product['Product']['antal'] - $amount;
$this->saveField('Product.antal',$final_amount);
find(), as documented, uses conditions array to retrieve records
$product = $this->Product->find('first', array('conditions' => array('id' => $id)));
See http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#find-first
Sidenote:
$this->id is currently mainly used for saving records, to be able to easily read the new created primary key value (id).
It is also used for saving via saveField().
In your case then (after using find() to get the product array):
$this->Product->id = $product['Product']['id'];
$this->Product->saveField('antal', $final_amount);
You shoud assign a value to $this->id when you want to update that row id with Model::save(), or want to read from that row with Model::read(). Setting $this->id prior to Model::find() has no effect on select queries.
if you will call Model::find('first') most probably it will find the first record by ordering records by column whose name is assigned to orderBy class attribute of model, by default perhaps its the id field and ordering must be ASC.
Ideal scenarioes for using $this->id = $intVar would be as under:
when calling
Model::save()//for updating records
Model::saveField();
Model::read();
Model::delete();//for deleting
Related
Code:
$item1 = Item::find(1);
$item1->foo = 1;
$item1->save();
$another_item1 = Item::find(1);
dd($another_item1->foo);//Is this value always 1?
My question:
Is always read the newly written data after calling save() method of ORM? In my example, Is $another_item1->foo always 1?
If the answer to question 1 is not, how could I ensure I read the newly written data from the database?
Is always read the newly written data after calling save() method of ORM?
No, there is no SELECT ran after a INSERT or UPDATE statement in this case.
In my example, Is $another_item1->foo always 1?
Based on your own comment, Yes.
If the answer to question 1 is not, how could I ensure I read the newly written data from the database?
$model->save();
// Reload the current model instance with fresh attributes from the database.
$model->refresh();
// OR
// Reload a fresh model instance from the database.
$fresh = $model->fresh();
I think you may be confused about the find() function. find() is used to fetch one or many models by its / their primary key(s). The return value will either be a single model, a collection or null if the record is not found.
If you are looking to lookup multiple rows you need to run Item::get();
Uses
$Item = Item::find(1); // returns model or null
$Items = Item::find(array(1, 2, 3)); // returns selected Items in collection
$Items = Item::get(); // Returns all in collection
https://laravel.com/docs/5.5/eloquent
Am having a table with id as primary key not auto increment, I need to push the custom value as an ID. I tried with firstOrNew() and findOrCreate() and create() by pushing the ID as an argument like
$var_id = '99';
$var = Table::findOrCreate(['id'=>$var_id]);
return $var;
But its creating new row with 0 as ID. Can any one please suggest me how to create ID with 99.
Thanks
Did you create your table manually or through a migration? Make sure your id is set to "auto-increment" on your table. If you create through a migration it would look something like this $table->increments('id');
Try laravel query builder its flexible to use.
DB::table('tablename')->insert(
array('id' => '99'));
For more help check this link out
Laravel 4.2 query builder
I guess you're code has a small typo, in your case you probably want to use firstOrCreate or findOrNew.
Either way, by default all model attributes are guarded.
Add id to your model fillable array, like so:
protected $fillable = ['id']; // perhaps more ?
And try again.
I'm trying to update a model, I load the model, take all the data from the POST and then save it, easy... But my record was never updating so went to the log and discovered that the update query is adding a weird condition. FYI, MD_ID is my primary key.
So, I load the model, the next line is the SQL produced by Yii:
$model = Ositems::model()->findByPk($id);
SELECT * FROM "MTODETALLADO_INV" "t" WHERE "t"."MD_ID"=249217
If echo the json_encode of the loaded model I get that dictionary in my browser:
echo json_encode($model->getAttributes());
{""MD_BODEGA":"01","MD_PRODUCTO":"0031253","MD_CANTIDAD":"1","MD_PRECIOTOTAL":"1466",,"MD_PORCENTAJEDESCUENTO":"0","MD_IDCABECERA":"97403","MD_ID":"249217","MD_OBSERVACION":null}
At this point everything looks right, now I take the values from post:
$model->attributes = $_POST;
And here if echo the values of the model I get the new values right, now here is the problem: I save the model and this is the SQL Yii runs (I replaced the :yp_ values to make it more readable)
$model->save();
UPDATE "MTODETALLADO_INV" SET
MD_BODEGA"='01'
MD_PRODUCTO"='0020514
MD_CANTIDAD"='10'
MD_PORCENTAJEDESCUENTO"='0
MD_IDCABECERA"=97403
MD_ID"=249218
MD_PRECIOTOTAL"='36210'
MD_OBSERVACION"=''
WHERE "MTODETALLADO_INV"."MD_ID"=1
And there is the problem! WHERE "MTODETALLADO_INV"."MD_ID"=1, Why would it make it 1 if all this time my model id has been 249218 ?
A few considerations:
My model only takes some columns that I need from the actual table, Yii sets the other columns as null and I omitted them in the previous code.
The table is in a foreign db, I use have a custom ActiveRecord which manages the CDbConnection to a database according to the user. (It's a webservice app)
I followed what the function save() did and could finally find the problem was when it tried to get the primary key. I had this method in my model:
public function primaryKey()
{
return array('MS_ID');
}
}
But it had to be:
public function primaryKey()
{
return 'MS_ID';
}
}
Somehow that was causing the problem.
I'm pretty new to Doctrine, but as I understand it, the assignIdentifier() method is supposed to tell Doctrine to update the relevant row into the database instead of inserting a new one.
I have an object that I'm building through a workflow, so the identifier has an id of null until I call $object->save(); which inserts it, and this does work.
If however I call $object->assignIdentifier($newobj->id); and then $object->save(); it does nothing - it does not insert a new row and does not update the old one.
If a certain condition is true, I want to pull a different record out of the DB and update that row instead of inserting the new one.
Am I understanding something wrong here?
Some code to illustrate:
if($this->object->payments > 0) {
$older_payment = Doctrine_Query::create()
->from('OldPaid p')
->where('p.dealid = ?', $this->object->transid)
->fetchOne()
;
$this->object->assignIdentifier($older_payment->id);
}
$this->object->save();
Like i got to know, save() will not update an existing record with autoincrement on ID.
I have the same problem using doctrine 1.2.
an idea i have use this one, the only workaroung i found:
$query = Doctrine_Query::create()->update('OldPaid');
$query->set($yourFieldname, '?', $yourValue);
$query->addwhere('p.dealid = ?', $this->object->transid);
$query->execute();
Thiw will function when a record is in the DN with the primaryKey dealid = $this->object->transid.
greeting m
Usually, if you retrieve a record, you can update it with the save() method. Doctrine recognizes this (since the PK doesn't change) and updates the record.
From the docs:
Updating objects is very easy, you
just call the Doctrine_Record::save()
method
Another way can be replace(), but I usually use just save() and does either the saving or the updating if the record already exists.
As far as I can read from the description of assignIdentifier() never used it myself) it will only work with retrieving an object by its ID, so updating something with this method will not work.
I'm using the cacheCounter in CakePHP, which increments a counter for related fields.
Example, I have a Person table a Source table. Person.source_id maps to a row in the Source table. Each person has one Source, and each Source has none or many Person rows.
cacheCounter is working great when I change the value of a source on a person. It increments Source.Person_Count. Cool.
But when it increments, it adds it to the destination source for a person, but doesn't remove it from the old value. I tried updateCacheControl() in afterSave, but that didn't do anything.
So then I wrote some code in my model for afterSave that would subtract the source source_id, but it always did this even when I wasn't even changing the source_id. (So the count went negative).
My question: Is there a way to tell if a field was changed in the model in CakePHP?
To monitor changes in a field, you can use this logic in your model with no changes elsewhere required:
function beforeSave() {
$this->recursive = -1;
$this->old = $this->find(array($this->primaryKey => $this->id));
if ($this->old){
$changed_fields = array();
foreach ($this->data[$this->alias] as $key =>$value) {
if ($this->old[$this->alias][$key] != $value) {
$changed_fields[] = $key;
}
}
}
// $changed_fields is an array of fields that changed
return true;
}
With reference to Alexander Morland Answer.
How about this instead of looping through it in before filter.
$result = array_diff_assoc($this->old[$this->alias],$this->data[$this->alias]);
You will get key as well as value also.
You could use ->isDirty() in the entity to see if a field has been modified.
// Prior to 3.5 use dirty()
$article->isDirty('title');
check the doc: https://book.cakephp.org/3/en/orm/entities.html#checking-if-an-entity-has-been-modified
Edits happen infrequently, so another select before you do the update is no big deal, so, fetch the record before you save, save it, compare the data submitted in the edit form with the data you fetched from the db before you saved it, if its different, do something.
In the edit view, include another hidden field for the field you want to monitor but suffix the field name with something like "_prev" and set the value to the current value of the field you want to monitor. Then in your controller's edit action, do something if the two fields are not equal. e.g.
echo $form->input('field_to_monitor');
echo $form->hidden('field_to_monitor_prev', array('value'=>$form->value('field_to_monitor')));
See if the "save" uses some sort of DBAL call that returns "affected rows", usually this is how you can judge if the last query changed data, or if it didn't. Because if it didn't, the affected rows after an UPDATE-statement are 0.
You can call getAffectedRows() on any model class.
From class Model :
/**
* Returns the number of rows affected by the last query
*
* #return int Number of rows
* #access public
*/
function getAffectedRows() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db->lastAffected();
}