Doctrine default value vs null insert - mysql

There is something that bothers me. I've tried to find one clear answer but no luck so far.
I'm using Symfony3 and Doctrine2 and MariaDB.
Let's assume that I've created something like this in my entity:
/**
* #ORM\Column(
* name="status",
* type="boolean",
* options={"default": 0}
* )
*/
private $status;
Now thanks to this I have field with default value of 0 in database:
`status` tinyint(1) NOT NULL DEFAULT '0',
But what's the point of having this when every time I try to save data into database(I'm trying to save only for example 1 out of 10 fields):
$story->setContent('Test Content');
$em = $this->getDoctrine()->getManager();
$em->persist($story);
$em->flush();
I get:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'status' cannot be null
Because, of course rest of the fields on the object are null.
I can work around this by setting the default values in the constructor or by allowing for null values in the DB.
What if I don't want to do this? Is there any other way that I am missing here?
So what I would like to know:
are setting default value in entity or allowing nulls in DB only ways to do this?
is there something wrong with my logic here?
is there any cooler and cleaner way of doing this?

Like #Cerad commented, you just need to initialize the property in your actual entity class
/**
* #ORM\Column(
* name="status",
* type="boolean",
* options={"default": 0}
* )
*/
private $status = 0;

Related

Laravel uses wrong primary key updating mysql

I set a custom string typed primary key in Laravel 6.x, calling
$node=Node::create() is fine, but when calling $node->save() later to update, it uses where ‘instanceId’=0 to match the primary key, which throw an exception with MySQL 1292 error.
For table schema (migrate):
public function up()
{
Schema::create('nodes', function (Blueprint $table) {
$table->string('instanceId')->primary();
$table->string('regionId')->nullable();
$table->string('privateIp')->unique()->nullable();
$table->string('publicIp')->unique()->nullable();
$table->string('dnsRecordId')->unique()->nullable();
$table->unsignedTinyInteger('status')->default(0);
$table->unsignedInteger('userId');
$table->timestamps();
});
}
For model definition:
/**
* The primary key associated with the table.
*
* #var string
*/
protected $primaryKey = 'instanceId';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'instanceId',
'regionId',
'privateIp',
'publicIp',
'dnsRecordId',
'status',
'userId',
];
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'userId' => 'integer',
];
Looks like you didn't set the value of instanceId before calling $node->save().
so it looks like $node->instanceId was null and since instanceId is a primary key it can't be null.
To prevent such issue, you need to set the value of instanceId before saving it or else you can set the default random value of the instanceId in the createSchema.
$node->instanceId = str_random(20);
Thanks
Thanks to lagbox, this is really a RTFM problem.
When using string primary key $incrementing=false and $keyType=‘string’ are required, otherwise Laravel will assume the primary key is self incrementing integer.

Symfony Doctrine runs same queries

since the last update of my server which happened last month, I face an unusual problem with Doctrine.
When I run doctrine:schema:update --force, I the result "54 queries executed". The same result happens even if I don't change my entities.
When I run doctrine:schema:update --dump-sql to see the queries, I can see that same queries are run. Ex :
ALTER TABLE artisan CHANGE creator_id creator_id INT DEFAULT NULL;
ALTER TABLE user_connection CHANGE date date DATETIME DEFAULT NULL;
ALTER TABLE device CHANGE device_type device_type VARCHAR(500) DEFAULT 'ios' NOT NULL;
The problem is that columns are from the same type that the one changed by the query. I don't know why Doctrine want to change the type.
MariaDB version is 10.4.13 - Doctrine version is 2.5.14 - Symfony version is 2.8.42
Entity examples :
Device : device_type
/**
* #var string
*
* #ORM\Column(name="device_type", type="string", length=500, options={ "default":"ios" })
*/
private $device_type = "ios";
UserConnection : date
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime", nullable=true)
*/
private $date;
Artisan : Creator
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="MiddlewareBundle\Entity\User")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="creator_id", referencedColumnName="id", nullable=true)
* })
*/
private $creator;
There has been a pull request some years ago, have a look at https://github.com/doctrine/dbal/pull/2825 - it clearly states your problem:
Doctrine currently does not support MariaDB 10.2.7+. Schema creation/update is triggering infinite schema diffs
The code from this pull request has been included since doctrine/dbal:2.7.0, so you should consider updating at least that single package

How to delete specific column value from db in yii2

I want to delete updated value from db. Like if the notice is inserted of notice column in class table and I want to delete it. So what will be the query in yii2? Please help -
$model = Class::find()->where('id', $id)->one;
$model->delete();
Above query is for -
DELETE FROM class WHERE id = $id;
I want to write query like that in yii2 -
DELETE notice FROM class WHERE id = $id;
If you are searching using the primary key, you can use
$model = Class::findOne($id);
Then, for deleting (setting to null) the notice field, you just need to use
$model->notice = NULL;
$model->save();
Note that if the notice attribute is required, or not null, the save will fail.
Yii allows you to execute SQL command direct
https://www.yiiframework.com/doc/api/2.0/yii-db-command
$query = "DELETE notice FROM class WHERE id = {$id}";
Yii::$app->db->createCommand($query)->execute();

CakePHP 3.0-RC1 throws fatal error from index method in Baked controller

I'm testing CakePHP 3.0-RC1 for possible use on a new project. After installing, configuring and creating two (yes, two) database tables, I ran 'bake all' against both tables.
After dealing with the spurious foreign key references in the model (a foreign key defined as the primary key referencing itself? C'mon, now, Bakers!) I am hitting this error:
Error: Method Cake\ORM\Query::__toString() must not throw an exception
File /srv/www/htdocs/wmcb/cake/vendor/cakephp/cakephp/src/Database/Driver/Mysql.php
Line: 193
Not my code. ;)
The offending table definition:
-- -----------------------------------------------------
-- Table `ISOCountryCodes`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `iso_country_codes` (
`iso_country_code_id` VARCHAR(4) CHARACTER SET utf8 NOT NULL ,
`iso_country_name` VARCHAR(64) CHARACTER SET utf8 NOT NULL ,
`iso_country_name_french` VARCHAR(64) CHARACTER SET utf8 NOT NULL ,
PRIMARY KEY (`iso_country_code_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8
COMMENT = 'Look-up table of ISO 3166-1 Country Names and Codes'
;
The IsoCountryCodesController index method, as generated by bake:
/**
* Index method
*
* #return void
*/
public function index()
{
$this->paginate = [
'contain' => ['IsoCountryCodes']
];
$this->set('isoCountryCodes', $this->paginate($this->IsoCountryCodes));
$this->set('_serialize', ['isoCountryCodes']);
}
And the initialize method from IsoCountryCodesTable.php:
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
$this->table('iso_country_codes');
$this->displayField('iso_country_code_id');
$this->primaryKey('iso_country_code_id');
// $this->belongsTo('IsoCountryCodes', ['foreignKey' => iso_country_code_id']);
}
with the reflexive foreign key commented out.
This behaviour holds for both tables.
CakePHP 2.5 works correctly with the same database table definitions.
Remove the 'contain' part in the paginate array. You don't have any association to IsoCountryCodes
The reason you got that result when baking is that bake is a conventions-based too. It can only try doing its best based on the stablished conventions. One of those conventions is that any column ending in _id is a foreignKey to another table.
Another convention is that the primary keys of tables should be named id. When not following the conventions you will need to help bake figuring out or fixing its guessing errors in the code it generates.

Cakephp save array data in MySql Database using loop with create

I am facing strange problem first time. I am trying to insert simple records in database with Custom Auto Increment Values e.g 00001, 00002, 00003. but unable to get Incremented value. Each record get updated with same max number.
Controller Code
public function dobulk() {
for($i=0;$i<5;$i++) {
$data = array();
$this->Tmp->create();
$data['Tmp']['invoice_no'] = $this->Tmp->get_no();
$data['Tmp']['invoice_date'] = '2013-12-11';
$this->Tmp->save($data);
}
}
Model Code
public function get_no() {
$strSql = "SELECT
LPAD(IFNULL(RIGHT(MAX(invoice_no),5),0) + 1,5,'0') AS max_id
FROM tmps
;";
$result = $this->query($strSql);
$invoice_no = $result[0][0]['max_id'];
return $invoice_no;
}
Database Table
CREATE TABLE `tmps` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`invoice_no` varchar(20) DEFAULT NULL,
`invoice_date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
Thanks in advance.
You're probably running into the model cache.
From here: Bakery article on caching
If Model->cacheQueries == true, Cake will store the result of queries in memory. If it later sees an identical query, the result will be pulled from memory instead of hitting the database. This is only cached for the duration of a single page request. However, if a record is updated, the cache is not cleared. This is what gets most people unfamiliar with the cache.
So to make your code work, add this line to the top of the dobulk() function:
$this->Tmp->cacheQueries = false;
As you're running raw SQL inside your model, you might also have to change the query request inside get_no() to:
$result = $this->query($strSql, false);
Hope below solution will help you!
public function get_no() {
$strSql = "SELECT MAX(invoice_no) AS max_id FROM tmps;";
$result = $this->query($strSql);
$invoice_no = $result['Tmp']['max_id'];
return $invoice_no;
}
public function dobulk(){
$data = array();
$tempInvoiceNumber = $this->Tmp->get_no();
for($i=1;$i<=5;$i++) {
$data[$i]['Tmp']['invoice_no'] = tempInvoiceNumber+$i;
$data[$i]['Tmp']['invoice_date'] = '2013-12-11';
}
$this->Tmp->saveAll($data);
}