CakePHP migration re-organising column order - cakephp

I have added new column using migrations.
This is my new added field
$table->addColumn('lastname', 'string', [
'default' => null,
'limit' => 255,
'null' => false,
]);
This column added after modified field. I want to change column order and want to put it after column name. How can I do it using migrations ?

You can use after in option, In adding time
$table->addColumn('firstname', 'string', [
'default' => null,
'limit' => 255,
'null' => false,
'after' => 'name'
]);

Related

Error: SQLSTATE[42P01]: Undefined table: "Missing FROM-claouse entry for table

Hy I create a join query using cakephp find as shown below :
$test = $this->DiagnosisBind->find(
'all',
[
'table' => 'diagnosis_binds',
'alias' => 'dbinds',
'order' => 'dbinds.set_num ASC',
//'recursive' => 0,
'conditions' => [
'dbinds.deleted IS NULL',
'dbinds.diagnosis_id ='.$diagnosisData[0][0]['id']
],
'joins' => [
[
'type' => 'INNER',
'table' => 'diagnosis_treats',
'alias' => 'dtreats',
'conditions' => [
'dtreats.diagnosis_bind_id = dbinds.id'
]
],
[
'type' => 'INNER',
'table' => 'medical_masters',
'alias' => 'medmas',
'conditions' => [
'medmas.deleted IS NULL'
]
]
],
'fields' => [
'dtreats.id',
'dtreats.medical_name',
'dtreats.amount',
'dbinds.days'
]
]
);
When executing the query, I got this error :
I have read this post missing FROM-clause entry for table "Grupo" cakephp And solution is create a recursive (I have tried but failed) and use containable (I'm not suppose to create containable). So what's wrong in my find above. Thank you
Note:
I'm using cakephp 2.0
Postgresql
There are no table and alias options for query builder finders, they are only available for joins, so your main table will use the default alias as you can see in the query in the error message, and that alias is DiagnosisBind, hence using dbinds will cause an error.
Long story short, use DiagnosisBind instead of dbinds.
Side note, never ever inject data into single value conditions (or in the key of a key => value condition for that matter):
'dbinds.diagnosis_id ='.$diagnosisData[0][0]['id']
That's a possible SQL injection vulnerability!, always use the key => value syntax, or bindings:
'DiagnosisBind.diagnosis_id' => $diagnosisData[0][0]['id']

sonata_type_model - Set value to empty

Is there a way to allow to set an empty value in the sonata_type_model?
This is my current configuration:
->add('location', 'sonata_type_model', [
'class' => Location::class,
'property' => 'name',
'label' => 'Herkunft',
])
Simply add 'empty_value' => '' to the array.
Same problem here. I solved it with the help of Saving Hooks: preUpdate()
public function preUpdate($object)
{
if (!$this->getRequest()->request->get($this->getForm()->getName())['location']) {
$object->setLocation(null);
}
}
// Changed sonata_type_model to symfony entity type field
// Then add placeholder option witch recognized as empty value option in select box.
...
->add('location', null, [
'class' => Location::class,
'property' => 'name',
'label' => 'Herkunft',
'placeholder' => 'Your empty option label',
])

CakePHP Migrations - How to specify scale and precision

I'm Running CakePhp 2.7 with Migrations Plugin and a Postgresql DB.
Creating a field of type 'number' and specifying length 15,4 (scale 15, precision 4 - or any length) does not actually create the field with that precision and/or scale.
...
'license_fee' => array(
'type' => 'number',
'null' => true,
'length' => '15,6',
'default' => 0
),
...
The field is created with the correct type (numeric) but with no scale/precision here is the Postgres description of the created field.
license_fee | numeric | default 0
What I was expecting to see is this
license_fee | numeric(15,6) | default 0
I also tried using 'type' => 'decimal' but same happened. This might not be supported by the migrations plugin but I just want to know if anyone knows for sure what's going on.
Found here: http://docs.phinx.org/en/latest/migrations.html
In order to create a : decimal(9,3)
$table->addColumn('distance', 'decimal', [
'default' => null,
'null' => false,
'precision'=>9,
'scale'=>3
]);
After further investigation and some help from Cake Development Corp. It turns out that the correct to way specify precision and scale is by using "limit" not "length" like I was attempting. So it should be like this:
'license_fee' => array(
'type' => 'number',
'null' => true,
'limit' => '15,6', //this is where I was wrong by using length
'default' => 0
),
This will work also if using 'type' => 'decimal' which is actually the same datatype. The end result is as expected:
license_fee | numeric(15,6) | default 0
I hope this useful for someone.
For 3.10 version:
$table->addColumn('name', ['type' => 'decimal', 'length' => 10, 'precision' => 3])
At /vendor/cakephp/cakephp/src/Database/Schema/TableSchema.php are the valid keys that can be used in a column:
$_columnKeys = [
'type' => null,
'baseType' => null,
'length' => null,
'precision' => null,
'null' => null,
'default' => null,
'comment' => null,
];

CakePHP - Add custom values to User Object

I have added 4 more columns to my CakePHP Users table and I am trying to figure out how I can include these columns in the $this->Auth->user() object.
I've added the column information to my Users Model and Entity but still no joy. Currently my user object looks like this;
[
'id' => (int) 1,
'username' => 'admin',
'name' => 'Web Admin',
'email' => 'webteam#',
'role' => 'admin',
'created' => object(Cake\I18n\Time) {
'time' => '2016-02-09T16:04:46+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => object(Cake\I18n\Time) {
'time' => '2016-02-12T08:53:16+00:00',
'timezone' => 'UTC',
'fixedNowTime' => false
}
]
Where is this object created and is there a way I can add my custom values to it, without editing core CakePHP files?
Thanks for your help .
By default the built-in authenticators will fetch all fields in the tables schema.
You most probably just forgot to clear your cache (tmp/cache/models), which you should do whenever you make changes to your schemas.
In case one would want to specify what fields are being fetched, a custom finder would be needed.
See Cookbook > Controllers > Components > Authentication > Customizing Find Query
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'finder' => 'auth'
]
],
]);
In your UsersTable class
public function findAuth(\Cake\ORM\Query $query, array $options)
{
return $query
->select(['id', 'username', 'password', 'column_x', 'column_y']);
}
It should be noted that the fields required for authentication must always be included, ie like username and password!

Cakephp 3, Updating associated belongsto Data

So I have 2 models: Plugins and Imports.
The association is Plugins hasOne Imports:
$this->hasOne('Imports', [
'foreignKey' => 'plugin_id'
]);
and Imports belongsTo Plugins:
$this->belongsTo('Plugins', [
'foreignKey' => 'plugin_id',
'joinType' => 'INNER'
]);
My plugins-table dump looks like this:
CREATE TABLE `plugins` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(50) NOT NULL,
`pluginkey` varchar(100) NOT NULL,
`pluginname` varchar(255) DEFAULT NULL,
`description` text,
`integrationinstructions` text,
`date_available` datetime DEFAULT NULL,
`date_last_changed` datetime DEFAULT NULL,
`author` varchar(255) DEFAULT NULL,
`version` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
and my imports table is:
CREATE TABLE imports (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
plugintype VARCHAR(50) NOT NULL,
importedpluginkey VARCHAR(255) NOT NULL,
imported DATETIME NULL DEFAULT NULL,
plugin_id INT UNSIGNED NOT NULL,
FOREIGN KEY plugin_key (plugin_id) REFERENCES plugins(id)
);
Now i baked both controllers and everything works fine. I can save an import(will later be used to import xml files) and it is linked to a plugin.
But now I want to let the Plugindata update through data I add in an import.
For example let's say i have a Plugin called "sale" with the type Wordpress and the key "wp_sale". Now i want to update this plugin by adding an import. For example changing it's description or name.
If i understand this right, I would only need to pass the data I want to change in the plugins alongside the id.
But when I check the patchEntity that is going to be safed the Plugin Entity is always '[new]'=> true, and the id I passed is gone.
This is what my controller looks like:
public function add()
{
$import = $this->Imports->newEntity();
if ($this->request->is('post')) {
$import = $this->Imports->patchEntity($import, $this->request->data, ['associated' => ['Plugins']]);
if ($this->Imports->save($import)) {
$this->Flash->success(__('The import has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The import could not be saved. Please, try again.'));
}
}
$plugins = $this->Imports->Plugins->find('list', ['limit' => 200]);
$this->set(compact('import', 'plugins'));
$this->set('_serialize', ['import']);
}
And this is what my form looks like:
echo $this->Form->input('plugintype');
echo $this->Form->input('importedpluginkey');
echo $this->Form->input('imported');
echo $this->Form->input('plugin_id', ['options' => $plugins]);
echo $this->Form->input('plugin.pluginkey');
echo $this->Form->input('plugin.type');
echo $this->Form->input('plugin.id', ['value' => 1]);
I gave the plugin.id the value 1 just for the sake of testing, because I wanted to pass an id for the Plugin.
My postdata looks like this:
[
'plugintype' => 'wordpress',
'importedpluginkey' => 'wp_sale',
'imported' => [
'year' => '2015',
'month' => '11',
'day' => '24',
'hour' => '10',
'minute' => '38'
],
'plugin_id' => '1',
'plugin' => [
'pluginkey' => 'wp_sale',
'type' => 'wordpress',
'id' => '1'
]
]
And the patched Entity looks like this:
object(App\Model\Entity\Import) {
'plugintype' => 'wordpress',
'importedpluginkey' => 'wp_sale',
'imported' => object(Cake\I18n\Time) {
'time' => '2015-11-24T11:04:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'plugin_id' => (int) 1,
'plugin' => object(App\Model\Entity\Plugin) {
'pluginkey' => 'wp_sale',
'type' => 'wordpress',
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'pluginkey' => true,
'type' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[repository]' => 'Plugins'
},
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'plugintype' => true,
'importedpluginkey' => true,
'imported' => true,
'plugin_id' => true,
'plugin' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[repository]' => 'Imports'
}
Many Questions on this site are about association saving. But what i want is update associated data when adding new data in the import model.
The reasoning behind it is, that I want to be able to update my Plugins without editing everyone of them, and just use the xml import.
If the Question still is unclear feel free to ask and I will explain myself further. Thanks in advance!
Edit: To be clear, I basically need to change the data of a plugin using the import controller.
I now got the plugin entity in another function now, and i can save that with the import entity. However, it doesnt change anything in the plugin, so basically that does nothing.
The example in the linked docs seem to assume that the entities are set up in a way that they allow the primary key to be mass assigned, see
Cookbook > Database Access & ORM > Entities > Mass Assignment
The primary key needs to be accessible
By default, baked entities do not allow the primary key to be mass assigned, so you have to take care of that, for example by overriding the fields accessible state via the patchEntitity() options, like
$import = $this->Imports->patchEntity(
$import,
$this->request->data,
[
'associated' => [
'Plugins' => [
'accessibleFields' => ['id' => true]
]
]
]
);
See also Cookbook > Database Access & ORM > Saving Data > Changing Accessible Fields
Note that while the entity will still be flagged as "new", the saving process will (as long as the checkExisting option is not being set to false) test whether a record with the given primary key exists, and in case necessary mark the entity as "non-new" before proceeding, so that you'll end up with an update instead of an insert.
See also Cookbook > Database Access & ORM > Saving Data > Saving Entities
Just add dependent here, I think it will work then.
$this->hasOne('Imports', [
'foreignKey' => 'plugin_id',
'dependent' => true,
]);
Please see Cascading Deletes

Resources