How do I Implement AUTO_INCREMENT in a Yii2 Migration Using MySQL? - php

I have created a yii2 (v2.0.6) migration for a simple MySQL (v5.6.21) table. Everything works, except that I cannot figure out how to AUTO_INCREMENT the primary key. The problem seems to be that I am using a small integer rather than the more standard long integer datatype. Here is my migration code:
$this->createTable('{{%status}}', [
'id' => $this->smallInteger(8)->unique(),
//'id' => $this->primaryKey(11),
'description' => $this->string(20),
]);
$this->addPrimaryKey('','status','id');
I could get around the problem by using the ->primaryKey() method, which is commented out in line 3 above, but then yii creates a long integer datatype, and I am trying to avoid that. Any insight into the problem will be much appreciated.

If it is critical to have that column type, you can always change it:
$this->createTable('{{%status}}', [
'id' => $this->primaryKey(11),
'description' => $this->string(20),
]);
$this->alterColumn('{{%status}}', 'id', $this->smallInteger(8).' NOT NULL AUTO_INCREMENT');
(I've tested this with MySQL - it works)
However, like #scaisEdge says, it's usually not worth the troble.

Why not a simply primaryKey?, the format for integer(8) , integer(11) or primary key is always the same is always an integer long
then or you need a small int (max 5 digit) or you can use the normal $this->primaryKey() because
SMALLINT is for storage of 2 byte (value -32768 32767) an then
smallInteger(8) is not coherent. the numer 8 is for output not for store format. If you want 8 digit you need at least
INT of 4 byte -2147483648 2147483647 or more

$this->createTable('posts', [
'post_id' => "bigint(20) unsigned NOT NULL AUTO_INCREMENT",
'loc_id' => $this->integer(10)->unsigned()->notNull(),
"PRIMARY KEY (`post_id`,`loc_id`)",
], 'ENGINE=InnoDB DEFAULT CHARSET=utf8');

This works for me
$this->createTable('new_table',[
'id' => Schema::TYPE_PK.' NOT NULL AUTO_INCREMENT',
'name' => Schema::TYPE_STRING,
'age' => Schema::TYPE_INTEGER
]);
However you can simply use the below style and Yii will replace the 'pk' type of id based on your DBMS. for MYSQL it will be int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
$this->createTable('new_table',[
'id' => 'pk',
'name' => Schema::TYPE_STRING,
'age' => Schema::TYPE_INTEGER
]);

Another (imo more readable) approach is:
$this
->integer()
->unsigned()
->notNull()
->append('AUTO_INCREMENT');

Related

laravel 8 Composite primary key with updateOrCreate

I just want to ask why upset method in eloquant ORM we can update records with "Composite" primary keys, and we can not do that with updateOrCreate ? !!! I have a table that users insert and update in most of times and it's not a good idea to have one Primary Key "id" !!
if you are not using the model events you can Mute events for your action to avoid the error.
https://laravel.com/docs/8.x/eloquent#muting-events
ModelName::withoutEvents(function (){
ModelName::updateOrCreate(
[
'id' => 'test',
'second_id' => 0
],
[
'data' => 'some data'
]
);
});

Odoo PHP API and Laradoo - how to save many2many many2one and selection fields

Could someone please provide a simple example of the usage for dealing with Odoo's one2many, many2many and selection fields when using Laradoo (or ripcord)?
Specifically how one would use them with create() and update(). In Python, it seems as if these are dealt with using special tuple commands however for PHP documentation seems very hard to find for these types of things and it would be extremely helpful.
For illustrative purposes in my particular project, I haven't been able to figure out how to relate a CRM lead tag to a lead during the creation process using Laradoo:
$id = $odoo->create('crm.lead', [
'type' => 'lead',
'priority' => 0, <-- what do we pass here for this selection field?
'name' => 'Example',
'contact_name' => 'John Doe',
'phone' => '555-555-5555',
'email_from' => 'example#domain.com',
'description' => 'Just some text.',
'tag_ids' => [1], <-- What do we pass here for this one2many field?
]);
In the example above when trying to set the priority selection field to an int other than 0 fails and when trying to pass an array of tag_ids (1 is valid tag id in my project), the lead remains untagged.
First of all selection field values are just string values that need to be part of the field defined selection values.
The values for relational fields like Onetomany and Many2many are ruled by the command formated values that you could read at:
https://github.com/odoo/odoo/blob/11.0/odoo/models.py#L3020-L3055
For the php api usage with ripcord you could set the tag_ids field value like:
$id = $odoo->create('crm.lead', [
'type' => 'lead',
'priority' => '0',
'name' => 'Example',
'contact_name' => 'John Doe',
'phone' => '555-555-5555',
'email_from' => 'example#domain.com',
'description' => 'Just some text.',
'tag_ids' => array(array(4,1)),
]);
This translate as that 1 is the id of a known and already existing crm.lead.tag that you could link to the m2m tag_ids field using the command 4. This could also be expressed using command 6 to link multiple ids on the same command value:
'tag_ids' => array(array(6,0,array(1,2,3))),
where using command 4 it will be:
'tag_ids' => array(array(4,1), array(4,2), array(4,3)),

Laravel set incremental id value when seeding table

I'm trying to seed a MySql table using Laravel seeder class. The problem is that it is not assigning the id field (which is an incremental) value as I set. In the seeder class I got:
public function run()
{
Patropi\Entidade::create([
'id' => '0',
'nome' => 'entidade 0',
'cpfcnpj' => '12345678901'
]);
Patropi\Fornecedor::create([
'id' => '0',
'prioridade' => '0'
]);
}
On the database, the Fornecedor table id is a foreign key which references the Entidade id, that's why I want to have the same Id on both. The problem is, when it inserts on Entidade it doesn't put it as id = 0 but instead it gives the value of the last incremental + 1. How to force laravel to insert 0 there instead? Thanks in advance.
The reason why it happens is Guarding Attributes. The attributes listed in $guarded array are protected from changes, what means Laravel will ignore all your attempts to modify them. Sometimes this approach is also known as Mass Assignment Protection.
By defualt, Laravel protects "id", so you can't and don't need to set them manually, however there's a way how to stop this default behavior. They key is in unguard() method.
Here's how you can fix your code:
public function run()
{
Patropi\Entidade::unguard();
Patropi\Entidade::create([
'id' => '0',
'nome' => 'entidade 0',
'cpfcnpj' => '12345678901'
]);
Patropi\Fornecedor::create([
'id' => '0',
'prioridade' => '0'
]);
}
Storing NULL or 0 in the auto-incrementing field is one of the triggers to assign the next incremental value.
From the MySQL docs:
You can also explicitly assign 0 to the column to generate sequence numbers.
If you want to disable this functionality, you can turn on the NO_AUTO_VALUE_ON_ZERO sql mode. This will change MySQL so that only assigning NULL will assign the next incremental value, and will allow you to store 0 in the field. From the docs:
NO_AUTO_VALUE_ON_ZERO affects handling of AUTO_INCREMENT columns. Normally, you generate the next sequence number for the column by inserting either NULL or 0 into it. NO_AUTO_VALUE_ON_ZERO suppresses this behavior for 0 so that only NULL generates the next sequence number.
This mode can be useful if 0 has been stored in a table's AUTO_INCREMENT column. (Storing 0 is not a recommended practice, by the way.)
If you don't explicitly need the id to be 0, then I would not try to assign 0. If the id doesn't matter, then you can do this:
public function run()
{
$entidade = Patropi\Entidade::create([
'nome' => 'entidade 0',
'cpfcnpj' => '12345678901'
]);
Patropi\Fornecedor::create([
'id' => $entidade->id,
'prioridade' => '0'
]);
}
Or, if you have the Eloquent relationships setup:
public function run()
{
$entidade = Patropi\Entidade::create([
'nome' => 'entidade 0',
'cpfcnpj' => '12345678901'
]);
// assumes fornecedor() defines a hasone/hasmany relationship.
$entidade->fornecedor()->create([
'prioridade' => '0'
]);
}

Seed Multiple Specific Data on Laravel

I want to seed a database table by using local, s3 and rackspace using database seeder on Laravel. However, if I use this three specific name with the $faker->randomElement() method it just populate the same name multiple time and that's what I don't need. If possible, I also want to set the different value for the different column using s3 or rackspace storage name.
$factory->define(App\Storage::class, function (\Faker\Generator $faker) {
return [
'storage' => $faker->randomElement(['s3', 'local', 'rackspace']),
's3-key' => null,
's3-secret' => null,
's3-region' => null,
's3-bucket' => null,
'rackspace-username' => null,
'rackspace-key' => null,
'rackspace-container' => null,
'status' => 'active'
];
})
What would be the best way to achieve this?
There is a bug in the Faker/Provider/Baser.class, it is using this line of code inside the randomElement Function which is duplicating the same random element over and over for the same instance due to the fact it is using static:: keyword
static::randomElements($array, 1);
I'll report about it, for the moment use this piece of code:
$faker->randomElements(['s3', 'local', 'rackspace'],1)[0]

8 byte Integer with Doctrine and PHP

the players:
64bit linux with
php 5 (ZendFramework 1.10.2)
PostgreSQL 8.3
Doctrine 1.2
Via a Flash/Flex client i get an 8byte integer value.
the field in the database is an BIGINT (8 byte)
PHP_INT_SIZE show that system supports 8byte integer.
printing out the value in the code as it is and as intval() leads to this:
Plain: 1269452776100
intval: 1269452776099
float rounding failure ?
but what really driving me nuts is
ERROR: invalid input syntax for integer: "1269452776099.000000"'
when i try to use it in a query. like:
Doctrine_Core::getTable('table')->findBy('external_id',$external_id);
or
Doctrine_Core::getTable('table')->findBy('external_id',intval($external_id));
How i am supposed to handle this ? or how can i give doctrine a floating point number which it should use on a bigint field ?
Any help is much appreciated!
TIA
EDIT:
from the model:
$this->hasColumn('external_id', 'integer', 8, array(
'type' => 'integer',
'length' => 8,
'fixed' => false,
'unsigned' => false,
'notnull' => false,
'primary' => false,
));
Database field is bigint 8 bytes.
EDIT2:
http://bugs.php.net/bug.php?id=48924 seems to be the root of the problem
As you have already mentioned, you hit this bug.
To work around it, pass the parameter as a string and make sure it's converted to a BIGINT on the database side:
$q = Doctrine_Query::create();
$q->from('table AS t')
->where("t.external_id = CAST(:external_id AS BIGINT)", array(':external_id' => $external_id))
->limit(1);
$result = $q->execute();

Categories