I'm currently developing an administration interface with FOSUserBundle, but I'm facing an annoying issue:
I've created an Operator class to hold FOSUserBundle's users, which is mapped in Symfony2 using Doctrine ORM. The first letter of Operator is uppercase (the rest of the tables in the website are also prefixed with capital letters, so I didn't want to break that convention).
The issue is that when I log in my administration interface, an error pops saying:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'dbname.operator' doesn't exist
Obviously, the query should use dbname.Operator, not dbname.operator.
Any help would be much appreciated.
Thanks!
Edit: attached the class definition of the Operator Entity:
/**
* #ORM\Entity
* #ORM\Table(name="Operator")
*/
class Operator extends BaseUser {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
}
Have you run
doctrine:schema:update --force
To create the database table?
You can set the database table name in your entity.
If you use annotations, your entity should start something like this:
/**
* Operator
*
* #ORM\Table(name="Operator")
*/
class Operator
{
Related
I have created two entities of existing database tables, these tables use the doctrine conventions for table relationships, I need to relate the tables to be able to work, the entities work by consulting data, but not between them.
Table name "Articulos"
class Articulos
{
/**
* #ORM\Id()
* #ORM\Column(type="integer")
*/
private $ID_Articulo;
/**
* #ORM\Column(name="ID_Clasificacion_Articulo", type="integer")
* #ORM\ManyToOne(targetEntity="ClasificacionesArticulos")
*/
private $ID_Clasificacion_Articulo;
.......
Table name "ClasificacionesArticulos"
class ClasificacionesArticulos
{
/**
* #ORM\Column(name="ID_Clasificacion_Articulo", type="integer")
* #ORM\Id()
* #ORM\OneToMany(targetEntity="Articulos", mappedBy="ID_Clasificacion_Articulo")
*/
private $ID_Clasificacion_Articulo;
/**
* #ORM\Column(type="string", length=150)
*/
private $Codigo;
/**
* #ORM\Column(type="string", length=150)
*/
private $Nombre;
.........
When I consult any of the entities, returns result without children of relationships. I suppose it's because of the names of the fields id does not use the name strategies, but I can not change them in the database, I have to adapt to it by requirements.
If someone has an idea, I thank you very much
This can be accomplished by implementing custom Doctrine naming strategy. In Symfony entity, use camelCase to avoid any problems with naming. But, if you need specific table names follow the guide
You have to implement NamingStrategy class:
class CustomNamingStrategy implements NamingStrategy
{
}
register it as a service by adding following to the end of the the config/services.yaml :
app.naming_strategy.custom:
class: App\Service\CustomNamingStrategy
autowire: true
Then specify naming strategy by editing config/packages/doctrine.yaml as follows:
naming_strategy: app.naming_strategy.custom
I believe you are looking for propertyToColumnName method, as Doctrine says
If you have database naming standards, like all table names should be
prefixed by the application prefix, all column names should be lower
case, you can easily achieve such standards by implementing a naming
strategy.
I have been doing some research on this topic but so far I couldn't find anything helpful for my scenario.
In a brief: I have two tables Quote (table name: quote) and QuoteArchive (table name: quote_archive). Both share exactly the same columns and types. As far as I have read this turn into a Doctrine MappedSuper Class ex: MappedSuperclassQuote.
After that Quote and QuoteArchive entities will extend from the MappedSuperclassQuote and both will share exactly the same structure.
Quote has a custom Repository with some functions. QuoteArchive needs exactly the same Repository functions as in Quote with the only difference being the table name and the PK.
I have two doubts in this scenario:
How to extend Doctrine entities when the PK (#Id) is different in the child classes?
How to extend or share the same repository between entities when the only change is the table name.
For get a better idea this is how my current entities looks like:
/**
* #ORM\Entity
* #ORM\Table(name="quote")
* #ORM\Entity(repositoryClass="QuoteBundle\Entity\Repository\QuoteRepository")
*/
class Quote
{
/**
* #ORM\Id
* #ORM\Column(type="integer",unique=true,nullable=false)
* #ORM\GeneratedValue
*/
private $quoteId;
// ...
}
/**
* #ORM\Entity
* #ORM\Table(name="quote_archive")
* #ORM\Entity(repositoryClass="QuoteBundle\Entity\Repository\QuoteArchiveRepository")
*/
class QuoteArchive
{
/**
* #ORM\Id
* #ORM\Column(type="integer",unique=true,nullable=false)
*/
private $archiveId;
// ...
}
Last but not least:
class QuoteRepository extends EntityRepository
{
public function getCurrentQuoteId(int $OrigQuoteId)
{
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
return $qb->select('q')
->from('QuoteBundle:Quote')
->where('q.origQuoteId =:origQuoteId')
->setParameter('origQuoteId', $OrigQuoteId)
->andWhere('q.quoteType =:quoteType')
->setParameter('quoteType', 'current')
->getQuery()
->getResult();
}
}
What is the problem here? I need to repeat the same exact function in QuoteArchiveRepository and change the table from quote to quote_archive and it's exactly what I am trying to avoid if possible.
Can any give me some ideas? Code example would be great :)
References:
Can we extend entities in Doctrine?
Doctrine: extending entity class
Doctrine How to extend custom repository and call the extended repository from doctrine entity manager
I think you're mistaking doing a MappedSuperclassQuote entity.
You have to inherit the Archive from the Quote.
Example : you have your Quote entity
The definition should be something like :
/**
* #ORM\Table(name="app_quote")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="quote_type", fieldName="quoteType", type="string")
* #ORM\DiscriminatorMap({
* "quote":"YourBundle\Entity\Quote",
* "quote_archive":"YourBundle\Entity\QuoteArchive"
* })
* #Gedmo\Loggable
* #ORM\Entity(repositoryClass="YourBundle\Repository\QuoteRepository")
*/
Why a JOINED inheritance ? Cause you want two separate tables (what SINGLE_TABLE is not doing) and you don't have a really abstract class (cause Quote AND QuoteArchive means something for you)
After, your table QuoteArchive should extends the first one :
/**
* #ORM\Entity
* #ORM\Table(name="app_quote_archive")
*/
class QuoteArchive extends Quote
{
...
}
Your column quote_type in app_quote will help you to know if this is an archived quote or not.
It provides you all you want :
- QuoteArchive will have access to functions inside QuoteRepository
- Each table has separated ids
One thing could be annoying for you : if you want to set a quote has archived, it's not so easy to change an entity type for now in Doctrine. In that case, it's better for you to use single_table joining type. All the datas are stored in a same table in database, making type change easy but you keep two different entities.
I am currently designing a web application with Symfony 2.5 (and Doctrine 2.4.2) that has to be flexible to easily plug in new modules/bundles.
So I have an entity (let say A) that has two one-to-one associations with abstract classes (B and C). The future modules will implement one of the two abstract classes. Since the associations are one-to-one, I made them the ID of the abstract classes to ease the access to them when we know the ID of an instance of A
So here is what the code looks like:
class A:
<?php
namespace Me\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table()
* #ORM\Entity
*/
class A
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="B", cascade={"all"}, mappedBy="a")
* #ORM\JoinColumn(name="id", referencedColumnName="a_id")
*/
private $b;
/**
* #ORM\OneToOne(targetEntity="C", cascade={"all"}, mappedBy="a")
* #ORM\JoinColumn(name="id", referencedColumnName="a_id")
*/
private $c;
}
class B:
<?php
namespace Me\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table()
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
*/
abstract class B
{
/**
* #ORM\Id
* #ORM\OneToOne(targetEntity="A", inversedBy="b")
* #ORM\JoinColumn(name="a_id", referencedColumnName="id")
*/
private $a;
}
I will not post the code of the class C since it is the same as class B.
In my point of view, it seems all good. Even for the mapping verification command.
Indeed, when I execute php app/console doctrine:schema:validate, it tells me my schema is valid. However, this command then try to compare my schema to the schema in the database and it just fails at that point. php app/console doctrine:schema:update --dump-sql fails in the exact same way. So it is pretty embarrassing since it tells me my schema is valid but it cannot use it properly.
The error:
[ErrorException]
Warning: array_keys() expects parameter 1 to be array, null given in /vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php line 95
The error appears as soon as I add the InheritanceType and DiscriminatorColumn annotation to the classes B and C. Thing is that it tells me my schema is valid.
So does anyone have any clue if I am doing something wrong? Or is it definitely a bug in Doctrine? Do you have any other idea that would bring at least as much flexibility as my current solution?
Elioty
EDIT: I changed the owning side to be the abstract classes B and C since, accordingly to the doc, the owning side is the one with the foreign key and must use inversedBy attribute. Even with these changes, my schema is still valid and the same error still occurs.
EDIT2: If I create another field in B (and C) to hold the identity of the entity instead of the one-to-one association, the error disappears but it is no more like my valid schema.
EDIT3: I had a chat with a member of Doctrine's development team and (s)he told me it definitely looks like a bug. Bug report here.
First of all, the command php app/console doctrine:schema:validate checks the validity of the current schema. The current schema is the one generated by your last called to the command php app/console doctrine:schema:update --force
On the other hand the command php app/console doctrine:schema:update --dump-sql does not execute an actual update to the schema, though it may find some errors some others will not be come up...
I dont understand class B. The identity of this (abstract) class is a OneToOne relationship? Anyway, the thing is that Doctine will ignore the #ORD\Id if you don't add inheritanceType definitions. When you add this inheritanceType definition Doctrine will make attribute 'a' the primary key of B. Also it will create another attribute named 'a_id' which will serve as a foreign key for future subclasses (extends of B). But...relationships are not inherited.
Hope this helps...
I'm having trouble using entity inheritance in Symfony2. Here are my two classes:
use Doctrine\ORM\Mapping as ORM;
/**
* #Orm\MappedSuperclass
*/
class Object
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
}
/**
* #Orm\MappedSuperclass
*/
class Book extends Object
{
}
When I run php app/console doctrine:schema:create I get the following error:
[Doctrine\ORM\Mapping\MappingException]
Duplicate definition of column 'id' on entity 'Name\SiteBundle\Entity\Book' in a field or discriminator column mapping.
What may be causing this?
Thanks :)
Update:
You are right I missed this. Now I'm using single table inheritance with both classes being entities:
/**
* #Entity
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"object" = "Object", "book" = "Book"})
*/
But I still get the same error message.
Actually I found yml files in Resources/config/doctrine/, which were defining my entities, instead of just using annotations.
I removed these files and it's working now.
Thanks for your help !
I had same issue even after adding definitions to yml file. I was trying to add weight & max weight to a class and was getting:
Duplicate definition of column 'weight_value' on entity 'Model\ClientSuppliedProduct' in a field or discriminator column mapping.
Then I realized it requires columnPrefix to be different for similar types of fields and adding following in yml solved it for me:
`maxWeight:`
`class: Model\Weight`
`columnPrefix: max_weight_`
I had the same problem and error message but for me it was the other way around as #user2090861 said.
I had to remove the (unused)
use Doctrine\ORM\Mapping as ORM;
from my entity files, cause my real mapping comes from the orm.xml files.
I hope I can help with my answer many other people, cause this exception drove me crazy the last two days!
I ran into this in a different context - in my case, I had set up an entity for single-table inheritence using #ORM\DiscriminatorColumn, but had included the column in my class definition as well:
/**
* #ORM\Entity(repositoryClass="App\Repository\DirectoryObjectRepository")
* #ORM\InheritanceType("SINGLE_TABLE")
* #ORM\DiscriminatorColumn(name="kind", type="string")
*/
class DirectoryObject {
// ...
/**
* #ORM\Column(type="string", length=255)
*/
private $kind;
}
Removing the #ORM\Column definition of kind fixed this issue, as Doctrine defines it for me.
Sometimes it's impossible to remove extra config files, because theay are located in third party bundle and auto_mapping is enabled.
In this case you should disable undesirable mappings in app/config.yml
doctrine:
orm:
entity_managers:
default:
mappings:
SonataMediaBundle: { mapping: false }
Any entity must contain at least one field.
You must add at least one field in Book Entity
Example
/**
* #Orm\MappedSuperclass
*/
class Book extends Object
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
}
I had the same error message but I had made a different mistake:
Class B had an ID and extended Class A which also had an ID (protected, not private). So I had to remove the ID from Class B.
As I am creating a web application that will be used in research on patients in the health domain, I want all my users to be completely anonymous. Can I in a simple way get rid of the email and email_canonical fields without rewriting stuff in the bundle itself, for instance by doing something to my User Class in my own bundle?
EDIT: I did this:
/**
* #ORM\Column(nullable=true)
**/
protected $email;
/**
* #ORM\Column(nullable=true)
**/
protected $emailCanonical;
In my User entity class. Bu twhen I do php app/console doctrine:schema:update --force i get
[Doctrine\ORM\Mapping\MappingException]
Duplicate definition of column 'email' on entity 'Pan100\MoodLogBundle\Enti
ty\User' in a field or discriminator column mapping.
EDIT 2: Forgot to say this is done in a class extending the FOUserBundle's model class User as BaseUser...
OK!
I did:
...
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="email", column=#ORM\Column(nullable=true)),
* #ORM\AttributeOverride(name="emailCanonical", column=#ORM\Column(nullable=true, unique=false))
*
* })
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
...(code emitted)
Later I will find out if more is needed - I will probably have to override some of the FOSUserBundle methods for creating users. At least the "php app/console fos:user:create testuser" command requires an email... But it does not have to be unique anymore, so if I am hindered later I can just add the string "none" or something...