I am wondering how to reset a field to the DEFAULT value (the one set in MySQL structure) when performing an update action in CakePHP. Like using the DEFAULT keyword in SQL:
INSERT INTO items (position) VALUES (DEFAULT);
edit: I am not searching for a way to use the default on create, I am rather looking for a way to reset the field to it's default when it has been already used.
You can simply unset the form input from the requested array, if you want to save its default value into the mysql database. You can try the following to achieve the same:
$item_details = $this->request->data;
unset($item_details['Item']['position']);
$this->Item->create();
$this->Item->save($item_details);
According to your edited question, if you want to reset any field during updating a record. you just need to use the MySql default() function.
$item_details = $this->request->data;
$this->Item->id = $item_details['Item']['id'];
$this->Item->saveField('position', DboSource::expression('DEFAULT(position)'));
To answer my own question, it could be done with:
$this->Item->saveField('position', DboSource::expression('DEFAULT(position)'));
or
$data['Item']['position'] = DboSource::expression('DEFAULT(position)');
$this->Item->save($data)
But - and here we go with the lost hours: to be able to use DboSource there had to be a database query before! Otherwise CakePHP throws the error Class 'DboSource' not found.
Related
I have a case where I need to use conditional updates/inserts using peewee.
The query looks similar to what is shown here, conditional-duplicate-key-updates-with-mysql
As of now, what I'm doing is, do a get_or_create and then if it is not a create, check the condition in code and call and insert with on_conflict_replace.
But this is prone to race conditions, since the condition check happens back in web server, not in db server.
Is there a way to do the same with insert in peewee?
Using: AWS Aurora-MySQL-5.7
Yes, Peewee supports the ON DUPLICATE KEY UPDATE syntax. Here's an example from the docs:
class User(Model):
username = TextField(unique=True)
last_login = DateTimeField(null=True)
login_count = IntegerField()
# Insert a new user.
User.create(username='huey', login_count=0)
# Simulate the user logging in. The login count and timestamp will be
# either created or updated correctly.
now = datetime.now()
rowid = (User
.insert(username='huey', last_login=now, login_count=1)
.on_conflict(
preserve=[User.last_login], # Use the value we would have inserted.
update={User.login_count: User.login_count + 1})
.execute())
Doc link: http://docs.peewee-orm.com/en/latest/peewee/querying.html#upsert
I'm a noob in cakephp. Working on an opensource project. The issue is:
When I'm inserting a value for a certain table ( "is_adjusted" (tinyint)), the my php code executes successfully. But the table is only taking 0 or 1 as it's value. Sample code :
$reward = $ta_customer_reward->newEntity();
$string_reward = var_export($reward, true);
$reward->customer_email = $some_preset_xyz;
$reward->reward_amount = $some_preset_xyz;;
$reward->particulars = $some_preset_xyz;
.. .. ..
// This is_adjusted is the culprit.
$reward->is_adjusted = 2;
$reward = $ta_customer_reward->save($reward);
Now whenever I save (insert) this in db, this is stored as 1. I'm stuck for three days. Things I've checked:
No default value in db for is_adjusted.
No other function is overwriting that field.
*** 1.The reward object looked quite unusual to me. There is a property name dirty. I'm still studying this. But for now it seems to me as some cakephp db object structure.
This is cakephp v 3. xyz***
This is by CakePHP's design. CakePHP always see tinyint(1) as boolean hence it will always convert your value to true/false hence the 1/0.
To overcome this issue, use tinyint(2) instead for your column type. Remember to clear your model cache!
CakePHP data type documentation:http://book.cakephp.org/3.0/en/orm/database-basics.html#data-types
Blog post about this:http://blog.room34.com/archives/2649
Similar Q&A:CakePHP and tinyint as boolean
I have an enum column in a MySQL table called site_status:
From my understanding, updating the value of such a field is exactly the same process as changing value of a varchar or int or any other field.
The only "limitation" is that as a value I obviously have to set one from predefined values - as this is the nature of enum types. Right?
So I want to change site_status from LIVE to FREE:
I type:
update db_name.db_table set site_status = 'FREE' where site_id = 501;
Pretty easy query. Unfortunately does nothing. It also doesn't produce any error. Simply:
0 rows affected.
What am I doing wrong? When I manually click via GUI in Sequel Pro, the value is changed to FREE with no issues. I see a dropdown from which I pick another option.
The following query:
select replace(`Abilities`, 'export_import', 'auto') from fl_account_types;
gives me 'auto,listings' correct replacement from Abilities column. However, when I execute:
update fl_account_types set `Abilities` = replace(`Abilities`, 'export_import', 'autos');
MySQL just omits 'export_import' string and replaces Abilities with 'listings' string.
What could be the reason?
The problem was that Abilities was of type SET and I was trying to replace with a value which was not listed in a definition of it. But I still do not understand why select replace works well and why MySQL do not throw an error.
In my model, I have a field named timestamp (MySQL type: timestamp) defined in safe validator and I'm unable to write it manually. Each time I call:
$model->timestmap = time();
$model->save();
model is saved (row created / updated), that is -- it passes validation without errors, but timestamp field is filled with default value of 0000-00-00 00:00:00 (I decided to remove default on update CURRENT_TIMESTAMP attribute, I don't want MySQL to handle this).
However, when I remove above code and attach CTimestampBehavior instead, field is being filled with correct values on both update and create, without any problems.
What can be happening or what am I missing? How can behavior update field without problems, while my manual attempt fails? Is this because column type is timestamp, not datetime or int?
I was always told, that first clue, why some attribute isn't saved, is because it is not listed among safe validator list or because it is listed on unsafe validator list. But this one is listed on safe list.
Your database field is a datetime field (i assume, looking at your default value), but your filling it with a unix timestamp. Try it with an CDbExpression instead:
$model->timestamp = new CDbExpression('NOW()');
$model->save();
I usually use $model->timestamp = date('Y-m-d H:i:s'), it works perfectly
As the other answers already suggested:
The timestamp needs to be converted into a MySQL compatible date format string somehow upon saving and the other way around when loading. Now you already discovered that the CTimestampBehavior does this for you but unfortunately it doesn't care about loading.
IMO the best solution for you is something along the way of:
public function beforeSave()
{
$this->timestamp = date('Y-m-d H:i:s', $this->timestamp);
return parent::beforeSave();
}
public function afterSave()
{
// Turn it back into a unix timestamp in case you want to continue working with the record
$this->timestamp = CDateTimeParser::parse($this->timestamp, 'yyyy-MM-dd hh:mm:ss');
parent::afterSave();
}
public function afterFind()
{
$this->timestamp = CDateTimeParser::parse($this->timestamp, 'yyyy-MM-dd hh:mm:ss');
return parent::afterFind();
}
It's a lot of work for a stupid timestamp and so for myself I have an auto type conversion behaviour that I link to my models. This behaviour uses the table metadata to take care of everything automatically. Might be a good idea to invest in that. I've thought about making mine open source but it's a bit of a mess atm ;)
But the code above will give you unix times to work with during executing and whilst saving it will temporary convert into a mysql datetime string
Hope that helps.