8 byte Integer with Doctrine and PHP - 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();

Related

Yii2 - decimal less than 1 without leading 0

Basically in my MSSQL DB the record has column of value 0.21, however in the view (model read from DB) it is .21 everywhere without leading 0. Is it possible to change this behavior?
I'm not a MSSQL expert, but in this case .21 is probably returned as a string by PDO. String .21 will be recognized as a number, so 1 + '.21' will return 1.21, but when you want to just display this string, no transformation will be done. The easiest way (at least from PHP side) would be to typecast this value to float:
echo (float) '.21'; // 0.21
You can also configure AttributeTypecastBehavior to do this automatically at active record level:
public function behaviors() {
return [
'typecast' => [
'class' => AttributeTypecastBehavior::class,
'attributeTypes' => [
'my_attribute' => AttributeTypecastBehavior::TYPE_FLOAT,
],
],
];
}

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

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');

Zend Framework - integer validator

Zend Framework seems to have a feature for validating integers (checked the /Validate/Int.php in the library for the purpose) which validates correctly float numbers as integer, while I want to show error when float number is given.
Here is a snippet from my form:
$form['my_int'] = new Zend_Form_Element_Text('my_int');
$form['my_int']->setLabel('My Int')
->setRequired(true)
->addFilter('StringTrim')
->addDecorator('Errors', array('placement'=>'prepend',
'class'=>'my-err'))
->addValidator('NotEmpty', true, array('messages' =>
array('isEmpty' => 'Please provide data')))
->addValidator('int', true, array(
'locale' => 'en_US',
'messages' => array(
'intInvalid' => 'Please provide valid data',
'notInt' => 'Please provide valid data'
)
));
So when I provide something different from string, integer or float, 'intInvalid' error is triggered and my custom message is shown. When float number like 1.23 is provided 'notInt' error is shown. The problem is when you provide e.g. 1.00, then the validator checks for "!Zend_Locale_Format::isInteger($value, array('locale' => $this->_locale))" and decides the input is integer and when you try to add float number in the the database in an integer field, you get error.
How should I organize my form validation so that when float number is provided, no matter what, to show error to the user?
You should add the Int filter to that element.
$element->addFilter(new Zend_Filter_Int());

Why AmazonDynamoDB::TYPE_STRING or NUMBER?

What are these constants defined in Amazon DynamoDB?
Can someone please explain the need of these constants?
Why are these placed in key of associative array?
I see a strange notation during putting items in table like
'Name' => array( AmazonDynamoDB::TYPE_STRING => 'Amazon S3')
PHP SDK guide says 4 type of constants.
TYPE_ARRAY_OF_NUMBERS
TYPE_ARRAY_OF_STRINGS
TYPE_NUMBER
TYPE_STRING
$dynamodb->batch($queue)->put_item(array(
'TableName' => 'Forum',
'Item' => array(
'Name' => array( AmazonDynamoDB::TYPE_STRING => 'Amazon S3'), // Hash Key
'Category' => array( AmazonDynamoDB::TYPE_STRING => 'Amazon Web Services'),
// Range Key
'Threads' => array( AmazonDynamoDB::TYPE_NUMBER => '0')
)
));
These constants reflect the four available Amazon DynamoDB Data Types:
String - Strings are Unicode with UTF8 binary encoding. There is no limit to the string size when you assign it to an attribute except
when the attribute is part of the primary key. [...]
Number - Numbers are positive or negative exact-value decimals and integers. A number can have up to 38 digits of precision after the
decimal point, and can be between 10^-128 to 10^+126. The
representation in Amazon DynamoDB is of variable length. [...]
String and Number Sets - Amazon DynamoDB also supports both Number Sets and String Sets.
[...] Note that, because it is a
set, the values in the set must be unique. String Sets and Number Sets
are not ordered; the order of the values returned in a set is not
preserved.
You will need to specify or handle these data types in various API calls, e.g. for the KeySchema in CreateTable or the Item in PutItem as seen in the example you provided.
The newest version of the AWS PHP SDK adds convenience methods to help make formatting your request easier. See the docs for the attributes() method. For example:
$dynamodb->put_item(array(
'TableName' => 'my-table',
'Item' => $dynamodb->attributes(array(
'id' => 1,
'key1' => 'value1',
'key2' => 'value2',
))
));
Seems much easier to work with this way.

Make doctrine load auto_increment value after save

I'm using Doctrine for database abstraction. Now I'd like to get the auto_increment primary key from the freshly-created (and save()'d) object - but $obj->toArray() shows me that the field is empty after calling save().
Is there a flag that I'm not aware of that does this? Or do I really have to query the object from the database?
Ensure that you have the autoincrement flag set when setting up your object in the setTableDefinition() method (or related YAML config file). If this flag isn't set, then Doctrine won't know to update it. You should have something that looks like this:
$this->hasColumn('id', 'integer', 4, array(
'type' => 'integer',
'length' => 4,
'fixed' => false,
'unsigned' => true,
'primary' => true,
'autoincrement' => true //this flag right here
)
);
Call refresh on the record instance before the toArray.

Categories