Add a MySQL field of type "bit" to a FuelPHP model - mysql

My schema has a column that is of type "bit(1)". I haven't found a way that this can be expressed in Fuel. They don't seem to support the "bit" type and can't properly build insert queries.
Is there a way (possibly undocumented) to get Fuel to support this?

hmm... the orm supposedly accepts the bit field.
i have created a model from database. Look my migration script and model, maybe it can help you.
Model
class Model_Test extends \Orm\Model
{
protected static $_properties = array(
'id',
'whatever',
);
protected static $_table_name = 'tests';
}
Migration script
builded from an existing table using the command: oil refine fromdb:model test
namespace Fuel\Migrations;
class Create_tests
{
public function up()
{
\DBUtil::create_table('tests', array(
'id' => array('constraint' => 11, 'type' => 'int', 'auto_increment' => true, 'unsigned' => true),
'whatever' => array('type' => 'bit'),
), array('id'));
}
public function down()
{
\DBUtil::drop_table('tests');
}
}
In the controller, you must be need cast the value as INT
$f = Input::post('whatever_post_field');
$o = Model_Test::forge(array('whatever' => (int)$f));
$o->save();

Related

How to migrate column type DOUBLE via cakephp phinx migrations?

I'm trying to migrate table from db1 to db2 with using Phinx migrations, but i have a problem with one table where i have column type DOUBLE. I know that supported types are there Phinx column type, but it is possible to specify FLOAT type to get DOUBLE in diff_migration ? I use cakephp version 3.5.6.
My example migration_diff
<?php
use Migrations\AbstractMigration;
class Diff003 extends AbstractMigration
{
public function up()
{
$this->table('test_double')
->addColumn('double1', 'float', [ // here type DOUBLE is changing to FLOAT
'default' => null,
'limit' => null,
'null' => true,
])
->addColumn('double2', 'float', [
'default' => null,
'limit' => null,
'null' => true,
])
->create();
}
public function down()
{
$this->dropTable('test_double');
}
}
The DOUBLE type has been implemented recently, and will probably be available in the next Phinx release (it's been added as of version 0.10.7), see https://github.com/cakephp/phinx/pull/1493.
Until then you can for example use the custom column type feature:
->addColumn('double1', \Phinx\Util\Literal::from('DOUBLE'), [
// ...
])
or manually add the columns via raw SQL, something like:
$this->execute('ALTER TABLE test_double ADD COLUMN double1 DOUBLE NULL');
or if you're adventurous, use the Phinx master branch until the stable release is available:
composer require robmorgan/phinx:dev-master
->addColumn('double1', 'double', [
// ...
])

Yii 2 Gridview - Search Query generates ambiguous fields

I am generating related records search query for Gridview use
I get this error :
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'dbowner' in where clause is ambiguous
The SQL being executed was: SELECT COUNT(*) FROM tbl_iolcalculation LEFT JOIN tbl_iolcalculation patient ON tbl_iolcalculation.patient_id = patient.id WHERE (dbowner=1) AND (dbowner=1)
I have two related models 1) iolcalculation and patient - each iolcalculation has one patient (iolcalculation.patient_id -> patient.id)
The relevant code in my model IolCalculationSearch is :
public function search($params)
{
$query = IolCalculation::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->sort->attributes['patient.lastname'] = [
'asc' => ['patient.lastname' => SORT_ASC],
'desc' => ['patient.lastname' => SORT_DESC],
];
$query->joinWith(['patient'=> function($query) { $query->from(['patient'=>'tbl_iolcalculation']); } ]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
$query->andFilterWhere([
'id' => $this->id,
'patient_id' => $this->patient_id,
'preop_id' => $this->preop_id,
'calculation_date' => $this->calculation_date,
'iol_calculated' => $this->iol_calculated,
The reason this error is generated is that each model has an override to the default Where clause as follows, the reason being that multiple users data needs to be segregated from other users, by the field dbowner:
public static function defaultWhere($query) {
parent::init();
$session = new Session();
$session->open();
$query->andWhere(['t.dbowner' => $session['dbowner']]);
}
this is defined in a base model extending ActiveRecord, and then all working models extend this base model
How Can I resolve this ambiguous reference in the MySQL code?
Thanks in advance
$query->andFilterWhere([
// previous filters
self::tableName() . '.structure_id' => $this->structure_id,
// next filters
]);
I think, that you are searching for table aliases.
(https://github.com/yiisoft/yii2/issues/2377)
Like this, of course you have to change the rest of your code:
$query->joinWith(['patient'=> function($query) { $query->from(['patient p2'=>'tbl_iolcalculation']); } ]);
The only way I can get this to work is to override the default scope find I had set up for most models, so that it includes the actual table name as follows - in my model definition:
public static function find() {
$session = new Session();
$session->open();
return parent::find()->where(['tbl_iolcalculation.dbowner'=> $session['dbowner']]);
}
There may be a more elegant way using aliases, so any advice would be appreciated - would be nice to add aliases to where clauses, and I saw that they are working on this....

Yii2 Gii Table Prefix

I allways setup table prefix - for this post lets say my prefix is abc_.
So in common\config\main-local.php. I have:
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=database',
'username' => 'user',
'password' => 'pwd',
'charset' => 'utf8',
'tablePrefix' => 'abc_',
],
...
I have worked on Yii1 and used gii to generate models.
In this version it generated files like: table.php.
Now I work with Yii2 and learn the differences:
gii generate files like abc_table.php. Yes - I checked "Use Table Prefix".
This is not ok because prefix should be transparent.
Could please anyone tell me what I'm doing wrong?
You may change the model class name AbcTest to Test. For future model generations, check the Use Table Prefix field in the Gii tool. Gii generate correct model like this:
class Test extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%test}}';
}
...
}
In tableName method, it returns '{{%test}}' if you check Use Table Prefix in the Gii tool. If you do not check the Use Table Prefix, this method return 'abc_test' and generated model class will be named as AbcTest.

Multiple database connections and Yii 2.0

I have two databases, and every database has the same table with the same fields, but how do I get all records from all of two databases at the same time in Yii 2.0?
First you need to configure your databases like below:
return [
'components' => [
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=db1name', //maybe other dbms such as psql,...
'username' => 'db1username',
'password' => 'db1password',
],
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=db2name', // Maybe other DBMS such as psql (PostgreSQL),...
'username' => 'db2username',
'password' => 'db2password',
],
],
];
Then you can simply:
// To get from db1
Yii::$app->db1->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll()
// To get from db2
Yii::$app->db2->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll()
If you are using an active record model, in your model you can define:
public static function getDb() {
return Yii::$app->db1;
}
//Or db2
public static function getDb() {
return Yii::$app->db2;
}
Then:
If you have set db1 in the getDb() method, the result will be fetched from db1 and so on.
ModelName::find()->select('*')->all();
Just to add:
I followed the answer provided but still got an error:
"Unknown component ID: db"
After some testing, here is what I discovered: The function getDB is only called AFTER a connection is made to db. Therefore, you cannot delete or rename 'db' in the config file. Instead, you need to let the call to 'db' proceed as normal and then override it afterwards.
The solution (for me) was as follows:
In config/web.php add your second database configuration below db as follows:
'db' => require(__DIR__ . '/db.php'),
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=name',
'username' => 'user',
'password' => 'password',
'charset' => 'utf8',
'on afterOpen' => function ($event) {
$event->sender->createCommand("SET time_zone = '+00:00'")->execute();
},
],
DO NOT rename db. Failure to find db will cause an error. You can name db2 whatever you like.
Now in the model, add the following code:
class ModelNameHere extends \yii\db\ActiveRecord {
// add the function below:
public static function getDb() {
return Yii::$app->get('db2'); // second database
}
This will now override the default db configuration.
I hope that helps somebody else.
Note: you can include the configuration for db2 in another file but you cannot include it in the db.php file (obviously). Instead, create a file called db2.php and call it as you do db:
'db' => require(__DIR__ . '/db.php'),
'db2' => require(__DIR__ . '/db2.php'),
Thanks
Our situation is a little more complex, we have a "parent" database which has a table that contains the name of one or more "child" databases.
The reason for this is that the Yii project is instantiated for each of our clients, and the number of child databases depends on the client, also the database names are arbitrary (although following a pattern).
So we override
\yii\db\ActiveRecord
as follows:
class LodgeActiveRecord extends \yii\db\ActiveRecord
{
public static function getDb()
{
$lodgedb = Yii::$app->params['lodgedb'];
if(array_key_exists( $lodgedb, Yii::$app->params['dbs'])) {
return Yii::$app->params['dbs'][ $lodgedb ];
}
$connection = new \yii\db\Connection([
'dsn' => 'mysql:host=localhost;dbname=' . $lodgedb,
'username' => Yii::$app->params['dbuser'],
'password' => Yii::$app->params['dbpasswd'],
'charset' => 'utf8',
]);
$connection->open(); // not sure if this is necessary at this point
Yii::$app->params['dbs'][ $lodgedb ] = $connection;
return $connection;
}
}
Before calling any database function, first set Yii::$app->params['lodgedb'] to the name of the database required:
Yii::$app->params['lodgedb'] = $lodge->dbname; // used by LodgeActiveRecord
Your model classes don't change except they extend from LodgeActiveRecord:
class BookingRooms extends \app\models\LodgeActiveRecord
If you're using schmunk42/yii2-giiant to generate model classes, there is a 'modelDb' property which you can set to use a database component other than 'db'.

Error: SQLSTATE[42000]: Syntax error or access violation with cakePHP

I am using the framework cakePHP for my application. I programmed it on localhost with xampp and try to upload it on my website now. It worked without any problems on localhost. Now there is only this one page, which does not work on the new server. The other sites (which use the database connection too) work alright.
For this one site the following message appears:
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'add' at line 1
SQL Query: add
The function add() looks like this.
public function add() {
//$this->create();
$word_id = $this->Word->getWord_id();
$save = $this->save(array('word_id' => $word_id, 'text' => $this->getText($word_id), 'mistake' => 0));
return $save['Game']['id'];
}
On localhost I used MySQL-Client-Version: mysqlnd 5.0.8-dev - 20102224 - $Revision: 310735 $ and PHP Version 5.3.8.
On the server I use MySQL-Client-Version: 5.1.62 and PHP Version 5.3.17.
Thank you very much for helping!
Edit:
The model 'Game':
class Game extends AppModel {
public $name = 'Game';
public $belongsTo = 'Word';
public $searchedWord = '';
public function addGame() { // Create new game
$word_id = $this->Word->getWord_id();
$save = $this->save(array('word_id' => $word_id, 'text' => $this->getText($word_id), 'mistake' => 0));
return $save['Game']['id']; // Build the hangman
}
}
When I debug $this->Game, the output is:
object(AppModel) {
useDbConfig => 'default'
useTable => 'games'
id => null
data => array()
schemaName => null
table => 'games'
primaryKey => 'id'
validate => array()
validationErrors => array()
validationDomain => null
name => 'Game'
alias => 'Game'
tableToModel => array(
'games' => 'Game'
)
cacheQueries => false
belongsTo => array()
hasOne => array()
hasMany => array()
hasAndBelongsToMany => array()
actsAs => null
Behaviors => object(BehaviorCollection) {
modelName => 'Game'
defaultPriority => (int) 10
}
whitelist => array()
cacheSources => true
findQueryType => null
recursive => (int) 1
order => null
virtualFields => array()
__backAssociation => array()
__backInnerAssociation => array()
__backOriginalAssociation => array()
__backContainableAssociation => array()
findMethods => array(
'all' => true,
'first' => true,
'count' => true,
'neighbors' => true,
'list' => true,
'threaded' => true
)
}
usually, if this error happens, you don't have the model instance, but an app model instance you work on. the app model instance doesnt have the add() method and directly queries the db with add().
so make sure your model is properly included. since you didnt show us the code how you call the method (and how you make the model available to the controller) I cannot offer any concrete advice, though.
if you manually include it:
$this->ModelName = ClassRegistry::init('ModelName');
add is a reserved word in MySQL and you're probably using it in a SQL query without "escape".
Check if you have any field named add in your database.
I just had this error and I felt pretty stupid. I'm sure this has been solved a long time ago, but in case anyone else comes across it...
Using your example I'll show basically what I also stupidly did in my Controller and how it caused the same type of error you had:
public function index($gameid = null, $letter = null) {
if ($gameid == null) {
// New game
$gameid = $this->Game->addGame();
}
}
Since you already have the instance (controller class) and you're not calling the Model method of addGame here, but the Controller's method, you simply remove the Game-> from your one-line command.
$gameid = $this->addGame();
Simple and easy oversight. That said, if you moved the addGame method to your Model class, it probably would have worked as expected. :)