I have a problem with a symfony 1.4 setup :
I created the schema.yml:
BlogCategory:
actAs: { Timestampable: ~ }
columns:
name: { type: string(255), notnull: true, unique: true }
BlogPost:
actAs: { Timestampable: ~ }
columns:
category_id: { type: integer, notnull: true }
title: { type: string(255), notnull: true }
body: { type: string(255), notnull: true }
relations:
BlogCategory: { onDelete: CASCADE, local: category_id, foreign: id, foreignAlias: BlogPosts }
(based on jobeet tutorial )
then it generated me the table schema.sql :
CREATE TABLE blog_category (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255) NOT NULL UNIQUE, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL);
CREATE TABLE blog_post (id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL, title VARCHAR(255) NOT NULL, body VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL);
which seems right to me.
And to finish I tried to add fixtures and load the data, my fixtures are as follows:
data/fixtures/categories.yml:
BlogCategory:
design:
name: Design
programming:
name: Programming
management:
name: Management
administrator :
name: Administrator
data/fixtures/posts.yml
BlogPost:
initial_post_1:
BlogCategory : design
title: Initial post 1
body: This post is an initial test number 1
initial_post_2:
BlogCategory : design
title: Initial post 2
body: This post is an initial test number 2
The php symfony doctrine:data-load command is generating me the categories but not the posts, so I tried :
php symfony doctrine:data-load data/fixtures/posts.yml
Invalid row key specified: (blog_category) design, referred to in
(blog_post) initial_post_1
Any idea why I can't laod the posts ? I've already tried to delete the db re-generate etc...
Okey so after many tests and git reset --hard HEAD to fix my datas, it seems that I had a problem with my BlogPost.class.php which contained an empty save() method override that was messing things up.
Plus, to rewrite data in the right way the command to use is:
php symfony doctrine:build --all --and-load
and not :
php symfony doctrine:data-load
Hope it could help anyone with the same problem !
Related
Hi everyone and thanks for help in advance!
I'm a newbe in a Symfony2 framework and I faced a question:
How to create bidirectional relationships from existing database?
At first I created database for my project and than I mapped it to the yml files;
Simply, DB looks like this:
Table user:
CREATE TABLE user (
`id` INT NOT NULL AUTO_INCREMENT ,
`login` VARCHAR(255) NULL ,
`password` VARCHAR(255) NULL ,
`customer_id` INT NOT NULL ,
PRIMARY KEY (`id`) ,
INDEX `fk_user_customer1_idx` (`customer_id` ASC) ,
CONSTRAINT `fk_user_customer1`
FOREIGN KEY (`customer_id` )
REFERENCES `customer` (`id` )
) ENGINE = InnoDB
Table customer:
CREATE TABLE IF NOT EXISTS `customer` (
`id` INT NOT NULL AUTO_INCREMENT ,
`surname` VARCHAR(45) NULL ,
`name` VARCHAR(45) NULL ,
`midname` VARCHAR(45) NULL ,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
If I'm right, "user" have Many-to-One relationship to the "customer"; and "user" is an owning side, "customer" is an inverse side;
Then I run these commands:
php app/console doctrine:mapping:import ShadowTestBundle yml --force
And got the result:
Shadow\TestBundle\Entity\User:
type: entity
table: user
fields:
id:
id: true
type: integer
unsigned: false
nullable: false
generator:
strategy: IDENTITY
login:
type: string
length: 255
fixed: false
nullable: true
password:
type: string
length: 255
fixed: false
nullable: true
manyToOne:
customer:
targetEntity: Customer
cascade: { }
mappedBy: null
inversedBy: null
joinColumns:
customer_id:
referencedColumnName: id
orphanRemoval: false
lifecycleCallbacks: { }
Shadow\TestBundle\Entity\Customer:
type: entity
table: customer
fields:
id:
id: true
type: integer
unsigned: false
nullable: false
generator:
strategy: IDENTITY
surname:
type: string
length: 45
fixed: false
nullable: true
name:
type: string
length: 45
fixed: false
nullable: true
midname:
type: string
length: 45
fixed: false
nullable: true
lifecycleCallbacks: { }
And conforming entities by run command:
php app/console doctrine:generate:entities ShadowTestBundle
Entities reflects correctly the yml-files;
But both yml-files and entities use only unidirectional links; is it possible to generate bi-directional links, or I must write it manually?
As far as I see, it should look like that:
Shadow\TestBundle\Entity\Customer:
type: entity
table: customer
fields:
...
midname:
type: string
length: 45
fixed: false
nullable: true
oneToMany:
user:
targetEntity: User
mappedBy: cart
lifecycleCallbacks: { }
And I also have a little subquestion:
Why on the owning side (User), which generated by Doctrine, field "inversedBy" is null?
The imported mappings generated by app/console doctrine:mapping:import are not always correctly reflecting the complete database structure i.e. when it comes to non-primary keys.
The mapping's inversedBy attribute is set to null because doctrine can't guess your owning-side-entity's desired $property name for storing the inverse-side entity from a database - therefore the mapping is generated without inversedBy set...
... which results in the auto-generated/expected property-name being the camelCase representation of the targetEntity as default / convention.
If you are not importing hundreds of tables i would recommend targeting these little corrections by hand and not linger over the import command.
it's worth checking the documentation.
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/tools.html#reverse-engineering
From the document,
Reverse Engineering is a one-time process that can get you started with a project. Converting an existing database schema into mapping files only detects about 70-80% of the necessary mapping information. Additionally the detection from an existing database cannot detect inverse associations, inheritance types, entities with foreign keys as primary keys and many of the semantical operations on associations such as cascade.
Hope this helps. Cheers!
In my vendor bundle, I have 2 mapped superclass : BaseSite and BaseSection (which are abstract).
In my application bundle, I have 2 entities that extends the 2 mapped superclass.
Everything works so far: I have access to the fields defined in the superclasses and I can add new ones in my application bundle if needed.
The problem is when I am trying to define my association mapping between those entities. (manyToOne between BaseSection and BaseSite).
If I define it in the BaseSection mapped superclass, I am able to run the command app/console doctrine:generate:entities AcmeDemoBundle, but it doesn't work when
I try to create the tables: (app/console doctrine:schema:update --dump-sql)
CREATE TABLE Section (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, siteId INT DEFAULT NULL, INDEX IDX_95E06DEFFADB670C (siteId), PRIMARY KEY(id)) ENGINE = InnoDB;
CREATE TABLE Site (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB;
ALTER TABLE Section ADD CONSTRAINT FK_95E06DEFFADB670C FOREIGN KEY (siteId) REFERENCES BaseSite(id) ON DELETE CASCADE
As you can see, it tries to reference the foreign key on a table that doesn't exists (BaseSite instead of Site). I'm guessing this is because the mapped superclass isn't aware of the table name defined in the application entity.
I could define the association mapping on the application entities instead, but that would mean that if someone wanted to use my bundle, he would have to define the mapping himself, which I would like to avoid.
Is there another way to do this or maybe I'm just missing something?
Here is my code:
Vendor :
File: vendor\bundles\Acme\DemoBundle\Resources\config\doctrine\BaseSite.orm.yml
Acme\DemoBundle\Entity\BaseSite:
type: mappedSuperclass
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: 255
nullable: false
// ...
File: vendor\bundles\Acme\DemoBundle\Resources\config\doctrine\BaseSection.orm.yml
Acme\DemoBundle\Entity\BaseSection:
type: mappedSuperclass
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
length: 255
nullable: false
// ...
manyToOne:
site:
targetEntity: Acme\DemoBundle\Entity\BaseSite
joinColumn:
name: siteId
referencedColumnName: id
onDelete: cascade
Application:
File: src\Application\Acme\DemoBundle\Resources\config\doctrine\Site.orm.yml
Application\Acme\DemoBundle\Entity\Site:
type: entity
table: Site
File: src\Application\Acme\DemoBundle\Entity\Site.php
<?php
namespace Application\Acme\DemoBundle\Entity;
use Acme\DemoBundle\Entity\BaseSite;
class Site extends BaseSite
{
}
File: src\Application\Acme\DemoBundle\Resources\config\doctrine\Section.orm.yml
Application\Acme\DemoBundle\Entity\Section:
type: entity
table: Section
File: src\Application\Acme\DemoBundle\Entity\Section.php
<?php
namespace Application\Acme\DemoBundle\Entity;
use Acme\DemoBundle\Entity\BaseSection;
class Section extends BaseSection
{
}
After reading the Doctrine manual on Inheritance Mapping its says:
This means that One-To-Many associations are not possible on a mapped superclass at all
It might be worth looking at the table inheritance features.
I'm trying to model a user which could be invited by another user. So I set up one-to-many self reference in my doctrine model.
User:
tableName: users
actAs:
Timestampable:
columns:
id:
type: integer(11)
primary: true
autoincrement: true
name:
type: string(255)
unique: true
password:
type: string(255)
email:
type: string(255)
[...]
invited_by:
type: integer(11)
relations:
Inviter:
class: User
type: one
local: invited_by
foreign: id
foreignAlias: Invitees
onDelete: SET NULL
onUpdate: CASCADE
options:
type: InnoDB
collate: utf8_unicode_ci
charset: utf8
This works just fine in MySQL, but if I try to save the record using the User objects save()-method in Postgres the following error is thrown:
SQLSTATE[42P01]: Undefined table: 7 FEHLER: Relation »users_id«
existiert nicht LINE 1: SELECT CURRVAL('users_id') ^. Failing Query:
"SELECT CURRVAL('users_id')"
I think it is something related to the self reference, but I can't find a mistake in my modeling. Anyone an idea on this?
The default name of a sequence attached to a serial column is tablename_colname_seq
currval is for retrieving the "current value" of a sequence.
So it would have to be:
SELECT currval('users_id_seq')
Your whole syntax is obviously made out for MySQL. Things like type: InnoDB, integer(11) or autoincrement don't make sense in Postgres.
I've fresh isntall of Symfony 1.4 with Doctrine ORM.
I'm looking to install the plugin sfDoctrineGuard. I followed the instructions here:
http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin
all works fine until this step:
symfony doctrine:insert-sql
when I get an error:
SQLSTATE[HY000]: General error: 1005 Can't create table 'kickboxing.#sql-2b5b_a8f' (error 150) Failing Query "ALTER TABLE profile ADD CONSTRAINT profile_sf_guard_user_id_sf_guard_user_id FOREIGN KEY (sf_guard_user_id) REFERENCES sf_guard_user(id)
It did seem to create some tables:
profile
sf_guard_forgot_password
sf_guard_group
sf_guard_group_permission
sf_guard_permission
sf_guard_remember_key
sf_guard_user
sf_guard_user_group
sf_guard_user_permission
any ideas?
UPDATE:
I'm after spotting this really has nothign to do with doctrine/symfony. The issue seems to be with mysql I ran the alter command above in MySQL and of course I get same error.
For reference on that I've Debian Squeeze installed and mysql 5.
UPDATE2 :
when i run
SHOW INNODB STATUS;
I get
LATEST FOREIGN KEY ERROR
110927 7:58:35 Error in foreign key constraint of table _kickboxing/#sql-2b5b_a86:
FOREIGN KEY (sf_guard_user_id) REFERENCES sf_guard_user(id):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
Looks like a mySql issue. You can get a full (better) description of the error by logging into the mysql console and running
show innodb status
then look for the LATEST FOREIGN KEY ERROR to get an idea of what went wrong
I am using Symfony 1.4.16 and to configure sfDoctrineGuardPlugin, I followed prettyscripts.com but the schema.yml should be as follows;
Note: user_id is integer(8) thats what the size of sf_guard's id column type is.
sfGuardUserProfile:
tableName: sf_guard_user_profile
actAs: { Timestampable: ~ }
options: { collate: utf8_unicode_ci, charset: utf8 }
columns:
id: { type: integer(8), primary: true, autoincrement: true }
user_id: { type: integer(8), notnull: true }
fullname: { type: string(80) }
email: { type: string(100) }
relations:
User:
class: sfGuardUser
foreign: id
local: user_id
type: one
onDelete: cascade
foreignType: one
foreignAlias: Profile
Let's say that I have YAML scheme looking like that :
Note:
options:
type: MyISAM
collate: utf8_unicode_ci
charset: utf8
actAs: { Timestampable: ~ }
columns:
content: { type: string, notnull: true}
order_id: int(5)
user_id : int
relations:
User:
foreignAlias: Notes
local: user_id
foreign: id
type: one
foreignType: man
onDelete: CASCADE
When performing :
$note->setOrderId(0);
$note->save();
I'm getting the following error :
1 validator failed on order_id (type)
MySQL store order_id as bigint(20).
I am using Ubuntu 9.10, Symfony 1.2, PHP 5 and MySQL 5.
EDIT :
Got a hint, if I remove all mention of the size in the YAML file, I get a second validator error for order_id (lenght) :-)
I got it. Replacing "int" by "integer" and getting rid of the size did the trick. Now the YAML file looks like :
Note:
options:
type: MyISAM
collate: utf8_unicode_ci
charset: utf8
actAs: { Timestampable: ~ }
columns:
content: { type: string, notnull: true}
order_id: integer
user_id : integer
relations:
User:
foreignAlias: Notes
local: user_id
foreign: id
type: one
foreignType: man
onDelete: CASCADE
I tried that because other people on the net had similar errors, solved replacing "varchar" with "string".
If someone get stuck into that and read this answer, have a beer in their names :-)
I know this is old...
I just thought I might clarify that valid doctrine types are "integer", "string", "float", "decimal", "object", "clob", "blob", "enum", "array".
Doctrine then translates the doctrine type into the correct database type for the chosen backend.
Thats why "int" failed the type validator, but "integer" works.