I've just started working with Propel and I love it, but I have a question regarding how to utilize multiple database connections. I know I can set stuff up in my schema to connect to multiple different databases, but I'm curious how to handle this in code.
The issue I have is multiple databases, and each of them has slightly different schemas with no data warehousing. As a result I have things resembling the following:
databaseName: westCoastUsers
table: users
column1: email
column2: password
column3: FirstName
databaseName: eastCoastUsers
table: users
column1: email
column2: password
column3: firstName
column4: lastName
Right now in PHP non-Propel version, I'm doing all this by hand, and switching databases manually as required. I'm hoping to streamline things a bit, and I'm curious how to model this. Is there a way I can just have something like eastCoastUser and westCoastUser models that each refer to the proper database/etc or am I trying to wedge in something not supported?
I read this: How to use two database in propel but am uncertain how to actually execute that in code.
Thanks for the help
In your schema files, you can provide a name for the class that represents your table. They do not have to use the same name as the table. You do this with the phpName attribute on the table element.
For example your schema.xml could contain something like this
<database name="westCoastUsers">
<table name="users" phpName="WestCoastUser">
...columns here...
</table>
...
</database>
<database name="eastCoastUsers">
<table name="users" phpName="EastCoastUser">
...columns here...
</table>
</database>
(edit, note that the name="westCoastUser" on the database element refers to the name of the database, not the classes with similar names)
Then at build time, propel will generate WestCoastUser, WestCoastUserQuery, WestCoastUserPeer, EastCoastUser, EastCoastUserQuery and, EastCoastUserPeer. Each class will connect using the database it was defined under in your schema.
I wrote this originally for symfony 1.2, but I believe it all applies.
I’m using Symfony 1.2.4 for this example.I have two databases, master and slave
If you are going to use multiple databases, there are a few things that you are going to need to do.
You will need separate schema files for both (master.schema.yml and slave.schema.yml)
To use build-sql and insert-sql, you will need multiple propel.ini files
You will need to add an attribute to your schema files to get them to build right
Step 1
Create the databases.yml with two separate connections:
dev:
propel:
param:
classname: DebugPDO
test:
propel:
param:
classname: DebugPDO
all:
propel:
class: sfPropelDatabase
param:
classname: PropelPDO
dsn: mysql:dbname=master;host=xxx.xxx.xxx.xxx
username: uname
password: pass
encoding: utf8
persistent: true
pooling: true
master:
class: sfPropelDatabase
param:
classname: PropelPDO
dsn: mysql:dbname=slave;host=xxx.xxx.xxx.xxx
username: uname
password: pass
encoding: utf8
persistent: true
pooling: true
Step 2
As mentioned you will need two schema files. Please notice that you will need to define a package attribute for the database that matches up to the tables, and in this case it is ‘lib.model.master’ for the master connection.
master.schema.yml
master:
_attributes:
package: lib.model.master
defaultIdMethod: native
my_table:
_attributes: { package: lib.model.master }
my_id: { type: INTEGER, size: '11', primaryKey: true, autoIncrement: true, required: true }
etc.....
slave.schema.yml
slave:
_attributes:
package: lib.model.slave
defaultIdMethod: native
auctionp:
_attributes: { package: lib.model.slave }
etc.....
Step 3
You will need to create separate propel.ini files. In this example I used propel-master.ini and propel-slave.ini. Each of these files need to be configured for their respective databases.
Step 4
You will need a good batch file to build your your databases using the propel tools. Mine looks like this:
From the application root:
symfony build-model; cp config/slave-propel.ini config/propel.ini; symfony propel:build-sql; symfony propel:insert-sql --no-confirmation; cp config/propel-master.ini config/propel.ini; symfony propel:build-sql; symfony propel:insert-sql --no-confirmation;
Step 5
You will need to clean out /lib/model if you already built your model using one database and are now doing a split. Deleting the files in the “map” and “om” directories and the root directory will help you avoid conflicts.
Step 6
To use the two databases in code, you will need to add a bit to the connection, like the following:
Example 1:
$object = self::doSelect($c, Propel::getConnection('master'));
Example 2:
$newObject->save(Propel::getConnection('slave'));
Example 3:
$con = Propel::getConnection("propel");
$sql = "ALTER TABLE runlinhp CHANGE class class_rat varchar(15)";
$stmt = $con->prepare($sql);
$stmt->execute();
Related
I'm working on a symfony 1.4 project which uses Doctrine 1.2. I want to add some custom property for fields inside my schema.yml. The purpose of this is to reuse schema.yml in some other place other than Doctrine, to maintain some meta data about the entity. I tried to add a customproperty as I shown in bellow sample.
TestEntity:
tableName: test_table
columns:
id:
type: integer(4)
primary: true
autoincrement: true
name:
type: string(200)
customproperty: true
But when I tried to do doctrine build model, now it fails giving the error as follows.
"Invalid schema element named "customproperty" at path "TestEntity->columns->name""
I checked the schema.php file in following location to debug the error.
symfony/lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Import/Schema.php
This error comes because the custom property we are specifying is not there in "$_validation" array. Once I added the "customproperty" into that array it stopped giving the error.
But what I did was a hack to doctrine library and is there any other better way to achieve this without touching the library files.
We are using Symfony to create some webservices. We use Doctrine-ORM to store entities and Doctrine-DBAL to retrive data because it's very light and can reuse the ORM (entity manager) connection.
When using Doctrine-DBAL, integer values are returned to PHP as strings and we want to have integer values, specially because they are retured to Javascript. Following this discussion How to get numeric types from MySQL using PDO? we have installed mysql native driver sudo apt-get install php5-mysqlnd and setup our symfony (dbal) configuration with PDO::ATTR_EMULATE_PREPARE = false :
doctrine:
dbal:
.
.
options:
20 : false # PDO::ATTR_EMULATE_PREPARES is 20
With this configuration we are getting integers when mysql fields are integers. So far so good.
But there is a new problem: When storing entities with boolean values through Doctrine-ORM the entity is not persisted. We see in the logs the INSERT and the COMMIT, but the record is not in the database (if we use a table with no boolean fields defined in the entity, the record is stored).
Furthermore, we don't get any Error or Exception, so we find this very dangerous. We think there is a bug in the PDO library but we have to look a bit more into it.
The question: Has anybody experienced this behaviour? any workaround? Should Doctrine account for this?
gseric's answer will work but with the effect of hydrating your entities with integers. To still get booleans in your entities you can simply extend Doctrine's BooleanType:
class BooleanToIntType extends \Doctrine\DBAL\Types\BooleanType
{
public function getBindingType()
{
return \PDO::PARAM_INT;
}
}
Then, in your application bootstrap:
\Doctrine\DBAL\Types\Type::overrideType('boolean', BooleanToIntType::class);
If it's not too late for you, you can fix this issue in your app bootstrap this way:
\Doctrine\DBAL\Types\Type::overrideType('boolean', 'Doctrine\\DBAL\\Types\\IntegerType');
After this line is executed Doctrine DBAL will map your PHP boolean values to PDO integers (PDO::PARAM_INT instead od PDO::PARAM_BOOL).
Problem
Hi, I"m working with a friend on a Symfony2 project. He's working on a Windows based computer and I'm on my Mac.
We setup the project and made the database model / entities (code first) on his computer. Now I wanted to start working on it as well so we did a SQL dumb to my localhost. I edited the parameters.yml to match my settings. The project can connect to the server.
But when I try to open a page where the database is used i get this error:
An exception occurred while executing 'SELECT t0.id AS id1, t0.name AS name2, t0.bigimage AS bigimage3, t0.smallimage AS smallimage4, t0.info AS info5, t0.city_id AS city_id6 FROM District t0':
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'socialgeogroep6.District' doesn't exist
500 Internal Server Error - DBALException
1 linked Exception: PDOException »
Just to be clear, the page is running normal on his computer; he gets the data as it should be.
Question
What can be the problem? I looked in my PHPmyAdmin over and over again and the database is there with all the fields and data...
(screen: http://gyazo.com/4a0e5f1ee6b1e29d2d277df5fc0d8aac)
I really can't imagine what the problem is.
I hope someone can help us!
It's likely a case issue. You have the district table on your database, but doctrine is asking for the District table.
You should configure doctrine to use lower case table name. Refer to the doctrine documentation http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#persistent-classes to know how to do so.
I just had exactly the same kind of problem because i'm writing code on windows and i need to deploy on linux.
The solution is to add in config.yml the line:
doctrine:
orm:
naming_strategy: doctrine.orm.naming_strategy.underscore
This work for my in symfony 2.7. Just put in config.yml:
doctrine:
# ...
orm:
# ...
entity_managers:
default:
naming_strategy: doctrine.orm.naming_strategy.underscore
Table name case issue
socialgeogroep6.District
It should be socialgeogroep6.district as per the screenshot. Check the Entity annotation.
A word of caution: Before reading this solution. This is strictly a solution for those who are trying to set up the framework.
I think since you are just starting to try out, what you could do is, drop database and then start everything afresh.
- mysql -uroot -proot
- show databases;
- drop database <dbname>;
Then, recreate the tables.
- app/console doctrine:database:create
- app/console doctrine:schema:create
A word of caution it might be a very BAD idea to do this in production environment if you have already created your controllers and data is already populated.
If you are using Orm, you can set up it like this
District.orm.yml
Project\Bundle\DuterteBundle\Entity\Vp:
type: entity
table: district//note the lowercase
repositoryClass: Project\Bundle\DuterteBundle\Repository\VpRepository
May be missed to add singular table name object.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Mapping extends Model
{
protected $table = 'mapping';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'user_id', 'mapping', 'name'
];
}
For some reason, my generated pages are using for the field name article_id instead of articleid as it is in my database and model. I have tried running "symfony doctrine:build --all" and "symfony doctrine:generate-module ..." multiple times to no avail.
Here is an example of a bad generated file:
./apps/frontend/modules/article/templates/_form.php: <?php echo link_to('Delete', 'article/delete?article_id='.$form->getObject()->getArticleId()
Any suggestions would be greatly appreciated!
Thanks in advance!
EDIT
I tried cleaning as recommended, I also tried deleting the module and rebuilding it.
EDIT 2
After running "symfony doctrine:build --all" I do see this as a reference to the yml file used:
>> file+ /tmp/doctrine_schema_97369.yml
Here is the Article section from the /tmp yml file:
Article:
columns:
ArticleID:
type: integer
primary: true
autoincrement: true
length: '4'
It is possible that if you changed this name in your schema, that the old model files have kept the old name. You can try to clean your model files using the task doctrine:clean-model-files
I'm using doctrine and trying to validate some models.
I have the following in my YAML schema:
User:
package: User
columns:
username:
type: string
notnull: true
notblank: true
minlength: 4
password:
type: string
notnull: true
If I create a new user, it always validates, regardless of what values I give it.
eg:
$testuser = new User();
$testuser->username = ' ';
if ( ! $testuser->isValid())
{
echo 'User is invalid!';
}
EDIT:
The above is just an example. It still validates even if values specified as NOT NULL in the schema are omitted.
The invalid method is never produced. Does anyone know what might be causing this?
Any advice appreciated.
Thanks.
the reason is: there's no isValid() function in your models which created by Doctrine. (in your models/generated/*.php)
Step 1.
refer to Doctrine Manual: you should put this in your bootstrap.php or any your php file header)
$manager->setAttribute(Doctrine_Core::ATTR_VALIDATE, Doctrine_Core::VALIDATE_ALL);
Step 2.
rebuild your models' files.
Step 3.
it should work now :)