I am trying to override two properties of FOSUserBundle's User mapping.
use FOS\UserBundle\Model\User as BaseUser;
...
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
* #ORM\Table(name="user")
* #UniqueEntity(
* fields={"emailCanonical", "zone"},
* errorPath="email",
* message="This email address is already in use."
* )
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="email", column=#ORM\Column(type="string", name="email", length=255, unique=false, nullable=false)),
* #ORM\AttributeOverride(name="emailCanonical", column=#ORM\Column(type="string", name="emailCanonical", length=255, unique=false, nullable=false))
* })
*/
class User extends BaseUser
{
...
Everything seems to be working fine, except when I generate accessors: Invalid field override named 'email'
The error is thrown here:
// Doctrine\ORM\Mapping\ClassMetadataInfo
public function setAttributeOverride($fieldName, array $overrideMapping)
{
if ( ! isset($this->fieldMappings[$fieldName])) {
throw MappingException::invalidOverrideFieldName($this->name, $fieldName);
}
Here, $this->fieldMappings only contains the fields of my child User and not of the parent (mapped superclass).
Anyone got a clue?
The way I managed to fix this issue with Invalid field override named [field] for class [class] was to also add the overwritten attribute in the class I overwritten it.
I'm using version Symfony v2.7.8 and Doctrine v1.6.1.
Example:
<?php
use FOS\UserBundle\Model\User as BaseUser;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*
* #ORM\HasLifecycleCallbacks
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="usernameCanonical",
* column=#ORM\Column(
* type="string",
* name="username_canonical",
* length=255,
* unique=false
* )
* )
* })
*/
class User extends BaseUser
{
/**
* #var string
*
* #ORM\Column(type="string", name="username_canonical", length=255, unique=false)
*/
protected $usernameCanonical;
...
}
EDIT:
You're right, there is mapping info in FOSUserBundle/Resources/config/doctrine/model/User.orm.xml...
<mapped-superclass name="FOS\UserBundle\Model\User">
...
<field name="usernameCanonical" column="username_canonical" type="string" length="255" unique="true" />
<field name="email" column="email" type="string" length="255" />
Just guessing: Maybe this xml orm config is not parsed properly? Or maybe you need to do the overwrites in xml too?
I know this is an old post, but i found a sulution, at least it worked for me, maybe it would be helpful for someone else.
Well, i had the same issue and i'm using a custom manager for the fos_user, in the declaration file config.yml under doctrine entity_manager custom manager i declared the mapping to FOS_userBundle, BUT what was missing is to tell FOS_user that we use a diffrent manager and that's by adding :
fos_user:
---- db_driver: orm
---- model_manager_name: MyCustom_Manager
Sorry to revive an old post. What worked for me was to remove the ORM annotation on the field and ensure the name in AttributeOverride was the same as the field name being overridden.
E.g. the ff ORM annotation
/**
* #var string
*
* #ORM\Column(type="string", name="username_canonical", length=255, unique=false)
*/
protected $usernameCanonical;
Should become:
#ORM\AttributeOverride(name="usernameCanonical",
column=#ORM\Column(
type="string",
name="username_canonical",
length=255,
unique=false
)
)
Then, remove the ORM annotation to ensure we don't get a "Duplicate mapping for column" error. The final class looks like:
<?php
use FOS\UserBundle\Model\User as BaseUser;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*
* #ORM\HasLifecycleCallbacks
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="usernameCanonical",
* column=#ORM\Column(
* type="string",
* name="username_canonical",
* length=255,
* unique=false
* )
* )
* })
*/
class User extends BaseUser
{
/**
* #var string
*/
protected $usernameCanonical;
}
Related
I have the following entity:
<?php
namespace App\Entity\Geo;
use Doctrine\ORM\Mapping as ORM;
/*
* #ORM\Entity(repositoryClass="App\Repository\Geo\CityRepository")
* #ORM\Table(name="geo_cities")
*/
class City
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
protected ?int $id = null;
/**
* Name of the city
*
* #ORM\Column(type="string", length=50, nullable=false)
*/
protected string $name;
/**
* Addition for name of city
*
* #ORM\Column(type="string", length=20, nullable=false)
*/
protected ?string $name_more = null;
// Setters and getters
}
This entity is considered as invalid in Symfony console.
When I execute php bin/console doctrine:mapping:info, it is not listed.
I tried to rename entity, the namespace, remove fields, add fields but in all cases, the entity is not valid.
Any idea ?
Note: I have another entity with same structure and it is valid for doctrine.
It's missing one * here
/*
* #ORM\Entity(repositoryClass="App\Repository\Geo\CityRepository")
* #ORM\Table(name="geo_cities")
*/
I am trying to use Unique and Hostname constraint together in Syfony 5.4 entity. Lets have:
/**
* #ORM\Column(name="domain", type="string", length=150, nullable=false, unique=true)
* #Assert\NotBlank()
* #Assert\Hostname()
*/
private $domain;
This validate without problems. But when I add Unique constraint, it fails with message - This value should be of type array|IteratorAggregate.
/**
* #ORM\Column(name="domain", type="string", length=150, nullable=false, unique=true)
* #Assert\NotBlank()
* #Assert\Unique()
* #Assert\Hostname()
*/
private $domain;
I need both validation, yes, in this case it fails on database INSERT, but I want to validate form. How is correct way?
Thank you
DR
If I understand correctly you want to validate that the domain (or hostname) is unique inside the database table. In that case, you would have to use UniqueEntity see https://symfony.com/doc/current/reference/constraints/UniqueEntity.html.
It is worth mentioning that this doesn't protect you against race conditions.
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #UniqueEntity("domain")
*/
class YourEntity
{
/**
* #ORM\Column(name="domain", type="string", length=150, nullable=false, unique=true)
* #Assert\NotBlank()
* #Assert\Hostname()
*/
protected $domain;
}
I have the following Doctrine Entity in Symfony 4.2:
When I run the migration the unique constraints and the indexes are not generated. The result of the Entity are just the following indexes in MySql:
PRIMARY (id)
identifier (identifier), Unique
Media.php
<?php
// src/Entity/Media.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\UniqueConstraint;
/**
* Common\Model\Entity\Media
*
* #Entity
* #Table(name="media",
* uniqueConstraints={
* #UniqueConstraint(name="virtual_unique",
* columns={"virtualname", "virtualfolder"})
* }
* indexes={
* #Index(name="idx_virtual", columns={"virtualname", "virtualfolder"})
* #Index(name="idx_identifier", columns={"identifier"})
* }
* )
*/
/**
* #ORM\Entity(repositoryClass="App\Repository\MediaRepository")
*/
class Media
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", nullable=true, options={"unique": true})
*/
private $identifier;
/**
* #ORM\Column(type="string", length=255, nullable=false)
*/
private $virtualname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $virtualfolder;
}
First, you have multiple annotation blocks for the same class. Just merge them and have a single annotation block for that entity.
And you are using serveral annotations directly, but not importing their definitions. Specifically:
#Entity
#Index
#UniqueConstraint
#Table
Either you:
Use them prefixed by #ORM(since you are doing use Doctrine\ORM\Mapping as ORM)
This is the most convenient and the one that's usually applied.
A complete fix:
/**
* Common\Model\Entity\Media
*
* #ORM\Entity(repositoryClass="App\Repository\MediaRepository")
* #ORM\Table(name="media",
* uniqueConstraints={
* #ORM\UniqueConstraint(name="virtual_unique",
* columns={"virtualname", "virtualfolder"})
* },
* indexes={
* #ORM\Index(name="idx_virtual", columns={"virtualname", "virtualfolder"}),
* #ORM\Index(name="idx_identifier", columns={"identifier"})
* }
* )
*/
class Media
{}
Or, you use the full namespace declaration in those annotations
You could also use the annotations with the full namespace, like #Doctrine\ORM\Mapping\Table, #Doctrine\ORM\Mapping\UniqueConstraint, etc; but that gets unnecessarily verbose very quickly.
Or, you could import each of the annotations independently
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\Index;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\UniqueConstraint;
But it also seems wasteful.
The approach you'll see on the docs is the first one. Import Doctrine\ORM\Mapping as ORM, and use the annotations hanging from there.
Probably you need change #Table to #ORM\Table and remove #Entity
try this:
/**
* #ORM\Entity(repositoryClass="App\Repository\MediaRepository")
* #ORM\Table(name="media",
* uniqueConstraints={
* #UniqueConstraint(name="virtual_unique",
* columns={"virtualname", "virtualfolder"})
* }
* indexes={
* #ORM\Index(name="idx_virtual", columns={"virtualname", "virtualfolder"})
* #ORM\Index(name="idx_identifier", columns={"identifier"})
* }
* )
*/
Clearing my cache did the trick for me.
I tried a few other suggestions, but after a cache:clear I got the index in my migration.
I have a "Company" entity with three fields : id, name and slug. The name is unique.
When I attempt to create a new Company with a name already used I get the following error :
An exception occurred while executing 'INSERT INTO companies (name, slug) VALUES (?, ?)' with params ["test", "test-1"]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'test' for key 'UNIQ_8244AA3A5E237E06'
I don't know why, but the #UniqueEntity does not show my error message. I also tried to put this line : #UniqueEntity(fields={"name"}, groups={"company"})
Here is the code of the class :
<?php
namespace Project\UserBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Company
*
* #ORM\Table(name="companies")
* #UniqueEntity(fields={"name"}, message="form.error.name.unique")
* #ORM\Entity
*/
class Company
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=50, unique=true)
* #Assert\NotBlank(message="form.error.name.not_blank");
* #Assert\Length(min="4", max="50", minMessage="form.error.name.length.min {{ limit }}", maxMessage="form.error.name.length.max {{ limit }}");
*/
private $name;
/**
* #var string
*
* #ORM\Column(length=170, unique=true)
* #Gedmo\Slug(fields={"name"})
*/
private $slug;
/**
* #ORM\OneToMany(targetEntity="Project\UserBundle\Entity\User", mappedBy="company")
* #Assert\Valid
*/
private $users;
}
Could you test this 3 possibilities and try to get the default message? (But it seems that you already tried the third one. Maybe luck with the others)
(Btw, you can not set a groups option in the UniqueEntity annotation)
/**
* User
*
* #UniqueEntity("name")
* #UniqueEntity(fields="name")
* #UniqueEntity(fields={"name"})
*/
class User
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", unique=true)
*
* #Assert\NotBlank
*/
private $name;
}
This syntax works for me:
#UniqueEntity("name", message="form.error.name.unique")
My problem is quite simple but i search for an hour without succeed, i would like to add some constraint to the UserEntity. For example, i would like to limit the length of a username
I think the best way is to not touche FOS in Vendor. I have create my own userBundle with my own layout.html etc ... But i cannot override attribut who is already existing in FosuserBundle (it's working for the layout overriding btw my userBundle is a child of FOS)
the funny thing is "id" has no problem for the overriding
My User entity :
<?php
namespace Diane\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Diane\UserBundle\Entity\UserRepository")
*/
class User extends BaseUser
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #ORM\Column(name="username", type="string", length=10)
*/
protected $username;
}
Fos User model :
<?php
namespace FOS\UserBundle\Model;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
abstract class User implements UserInterface, GroupableInterface
{
protected $id;
/**
* #var string
*/
protected $username;
...
}
i have already try to remove :
/**
* #var string
*/
Error message :
Doctrine\ORM\Mapping\MappingException] Duplicate definition of column
'username' on entity 'Diane\UserBundle\Entity\User' in a field or
discriminator column mapping.
Thanks for any idea you could give me
Try AttributeOverrides Doctrine annotation:
/**
* User
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Diane\UserBundle\Entity\UserRepository") / class User extends
*
* #ORM\AttributeOverrides({
* #ORM\AttributeOverride(name="username",
* column=#ORM\Column(
* name = "username",
* type = "string",
* length = 10
* )
* )
* })
*
*/
class User extends BaseUser
{