I've got 2 entities: Type and Asset for which you can see the definition below.
In order to display a list of Assets in my web app I need to generate an Asset name which is a concatenation of Type->name and Asset->id (eg: cat-158 or dog-15)
I've just added a method getName() to the Asset Entity that fetches the Type name and joins it with the Asset id. Is there a way to do this with annotations so that the name is built using a join statement when fetching the Asset? Basically a property on the Asset Entity that is filled with the proper name/id combination when fetching the Asset, without fetching the type when calling getName()?
<?php
class Asset
{
/**
* #ORM\Id
* #ORM\GeneratedValue("IDENTITY")
* #ORM\Column(type="integer")
* #var integer
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="\Type")
* #var \Type
*/
private $type;
/**
* Constructs a name from the type and id
* #return string
*/
public function getName()
{
return $this->getType()->getName() . '-' . $this->getId();
}
// SNIP ...
}
class Type
{
/**
* #ORM\Id
* #ORM\GeneratedValue("IDENTITY")
* #ORM\Column(type="integer")
* #var integer
*/
private $id;
/**
* #ORM\Column(type="string", length=200, unique=true, nullable=false)
* #var string
*/
private $name;
// SNIP ...
}
Try this ?
Class Asset extends Type{
}
Related
I have one entity Hike which have relation with another named Department
<?php
class Hike
{
private $id;
private $name;
private $description;
/**
* #ORM\ManyToOne(targetEntity=Department::class, inversedBy="hikes")
* #ORM\JoinColumn(nullable=false)
* #Assert\NotBlank(message="libdepartmentRequired")
*/
private $department;
// ...
}
<?php
class Department
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=3)
*/
private $department_code;
/**
* #ORM\Column(type="string", length=255)
*/
private $department_nom;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Hike", mappedBy="department")
*/
private $hikes;
// ...
}
In easyAdmin3 rendering is fine like
But when I sorting by department I see that easyAdmin3 sort by department's id, and I would like sorting by department_nom
I saw many solutions but they all using easyAdmin2 and easy_admin.yaml which no longer exists now.
There is a way to achieve that ?
Use configureCrud. Something like this should do the trick.
public function configureCrud(Crud $crud): Crud
{
return $crud
->setDefaultSort(['departement' => 'DESC'])
;
}
You can also use the filter to get the resultat wanted.
I keep getting the error in the title when I want to login using the FOSUserBundle on Symfony. The problem is, I already have an "id" for my User table from my database so I don't want to create an "id" field like they ask on the FOSUserBundle guide. I don't understand why it would give me this error when there is no more "id" field in my code.
Is this "id" field mandatory?
Here is the code of my User class (here called "Utilisateurs")`use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
/**
* Utilisateurs
*
* #ORM\Table(name="utilisateurs", indexes={#ORM\Index(name="FK_UTILISATEURS_id_sexe", columns={"id_sexe"}), #ORM\Index(name="FK_UTILISATEURS_id_niveau", columns={"id_niveau"})})
* #ORM\Entity
*/
class Utilisateurs extends BaseUser
{
public function __construct()
{
parent::__construct();
}
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=25, nullable=true)
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="prenom", type="string", length=25, nullable=true)
*/
private $prenom;
/**
* #var \DateTime
*
* #ORM\Column(name="date_naissance", type="date", nullable=true)
*/
private $dateNaissance;
/**
* #var string
*
* #ORM\Column(name="url_photo", type="string", length=100, nullable=true)
*/
private $urlPhoto;
/**
* #var integer
*
* #ORM\Column(name="id_utilisateur", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idUtilisateur;
/**
* #var \Site\UserBundle\Entity\Sexes
*
* #ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\Sexes")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_sexe", referencedColumnName="id_sexe")
* })
*/
private $idSexe;
/**
* #var \Site\UserBundle\Entity\Niveaux
*
* #ORM\ManyToOne(targetEntity="Site\UserBundle\Entity\Niveaux")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_niveau", referencedColumnName="id_niveau")
* })
*/
private $idNiveau;`
As you can see I already have an "id_utilisateur" field which is the id of this entity.
And here is the code of the entity information in XML: The XML Code
Also here is a screenshot of the error I get when I try to log in: The Error
I think the problem is that per convention the id field is often called just id and in some places FOS UserBundle is expecting exactly that, e.g. in the UserProvider.
There are a few ways you can get around this. For instance you could just write your own UserProvder (using the one linked above as a reference) where you substitute the id with your field. You might have to do this in other places as well.
The easier solution would be to just change your entity to something like this:
/**
* #var integer
*
* #ORM\Column(name="id_utilisateur", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
public function getId() { return $this->id; }
Similarly in xml this would look like this:
<id name="id" column="id_utilisateur" type="integer">
<generator strategy="IDENTITY" />
</id>
This way in your entity you will use the expected property and accessor method, but in the background it will map to the database field id_utilisateur, so you you don't have to make any changes to your database.
This should already solve your problems. When a new user is generated Doctrine will take map $user->getId() to user_table.id_utilisateur automatically. If your existing code is making use of the old get-method you could just keep it around and mark it as deprecated:
/**
* #deprecated Use getId() instead.
*/
public function getIdUtilisateur()
{
return $this->getId();
}
I got a ParentClass like this
/** #ORM\MappedSuperclass */
class BaseValue
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var field
* #ORM\OneToMany(targetEntity="Field", mappedBy="value", cascade="all")
*/
protected $field;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* #return field
*/
public function getField()
{
return $this->field;
}
/**
* #param field $field
*/
public function setField($field)
{
$this->field = $field;
}
}
And a child like this
* #ORM\Entity
* #ORM\Table(name="integers")
*/
class Integer extends BaseValue
{
/**
* #var integer
*
* #ORM\Column(name="value", type="integer", nullable=true)
*/
protected $value;
/**
* #return string
*/
public function getValue()
{
return $this->value;
}
/**
* #param string $value
*/
public function setValue($value)
{
$this->value = $value;
}
}
Now I would like to relate the child in another class like this
* #ORM\Entity
* #ORM\Table(name="fields")
*/
class Field
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var
* #ORM\ManyToOne(targetEntity="BaseValue", mappedBy="field", cascade="all")
* #ORM\JoinColumn(name="vid", referencedColumnName="id")
*/
protected $value; // but it does not work
It always gets me the following error:
[Doctrine\Common\Annotations\AnnotationException]
[Creation Error] The annotation #ORM\ManyToOne declared on property zmpim\Entity\Field::$value does not have a property named "mappedBy". Available properties: targetEntity, cascade, fetch, inversedBy
Both got mappedby,.. so the error seems to be senseless
Update:
A field has got values and labels. The values get inherited from BaseValue into IntegerValue, StringValue and later others...
My OneToMany Relation is a parent class of inheritance.
like this, now:
/** #ORM\MappedSuperclass */
class BaseValue
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var Field
* #ORM\OneToMany(targetEntity="Field", mappedBy="field", cascade="persist", orphanRemoval=true )
*/
protected $field;
And this is my ManyToOne:
/**
*
* #ORM\Entity
* #ORM\Table(name="fields")
*/
class Field
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(name="id", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var int|null
* #ORM\ManyToOne(targetEntity="BaseValue", inversedBy="value")
* #ORM\JoinColumn(name="vid", referencedColumnName="id", onDelete="CASCADE")
*/
protected $value;
It still give me an error, but now it is:
[Doctrine\ORM\ORMException]
Column name id referenced for relation from zmpim\Entity\Field towards zmpim\Entity\BaseValue does not exist.
Your Entity Field is the inversed side of your mapping so instead of using MappedBy declaration you have to use this
/**
* Inversed side
* #var int|null
* #ORM\ManyToOne(targetEntity="BaseValue", inversedBy="field")
* #ORM\JoinColumn(name="[your_name]", referencedColumnName="[id]", onDelete="CASCADE")
*/
protected $value;
To understand well inversedSide and MappedBy attributes you can read this:
Doctrine inverse and owning side
After reading again you are aware of your relationnal problem between the two of your entities, but if you declare ManyToOne annotation, you have to set inversedBy attribute or you'll get an error. And this is what you have.
You can't declare ManyToOne annotation with mappedBy attribute because it does not exist and throw an exception by Doctrine.
To resume :
ManyToOne association =>
* #ORM\ManyToOne(targetEntity="[yourEntity]", inversedBy="[Field]")
Be careful this side require the declaration of this :
* #ORM\JoinColumn(name="[your_name]", referencedColumnName="[id]", onDelete="CASCADE")
OneToMany =>
* #ORM\OneToMany(targetEntity="[An_Entity]",
* mappedBy="[Field]", cascade={"persist"}, orphanRemoval=true)
EDIT from your answer :
Your mapping is still incorrect, your data in InversedBy And mappedBy need to be switched.
I have five entities :
ProductA, ProductB, User, UserProductA and UserProductB. The two last ones are "intermediate" entites which contain the attributes of relationships between ProductA, ProductB and User.
I would like to make a ManyToOne relationship between UserProductA and UserProductB but it doesn't work. When I try to update the database, I get this error : Single id is not allowed on composite primary key in entity.
UserProductA (without the relationship) :
/**
* #ORM\Entity(repositoryClass="Gam\UserBundle\Entity\UserProductARepository")
*/
class UserProductA
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\FicheBundle\Entity\ProductA")
*/
private $producta;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\UserBundle\Entity\User")
*/
private $user;
/**
* #ORM\Column(type="string", length=1, nullable=true)
*/
private $attribute;
etc...
}
UserProductB (without the relationship) :
/**
* #ORM\Entity(repositoryClass="Gam\UserBundle\Entity\UserProductBRepository")
*/
class UserProductB
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\FicheBundle\Entity\ProductB")
*/
private $productb;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Gam\UserBundle\Entity\User")
*/
private $user;
/**
* #ORM\Column(type="string", length=1, nullable=true)
*/
private $attribute;
etc...
}
How can I make it work ?
I always get an exception with my entities. I tried to play with them. I checked on google which relation is the most appropriate for my entities... But I couldn't find the best configuration.
I'm making a website where you can create some albums.
A user can have multiple albums.So I have an entity Album and I have inside a user property :
/**
* Album
*
* #ORM\Table(name="album")
* #ORM\Entity(repositoryClass="Moodress\Bundle\AlbumBundle\Entity\AlbumRepository")
*/
class Album
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
** #ORM\ManyToOne(targetEntity="Moodress\Bundle\UserBundle\Entity\User")
** #ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="creationDate", type="datetime")
*/
private $creationDate;
/**
* #var \DateTime
*
* #ORM\Column(name="modificationDate", type="datetime")
*/
private $modificationDate;
/**
* #ORM\OneToMany(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Picture", cascade={"persist"}, mappedBy="album")
*/
private $pictures;
/**
* Constructor
*/
public function __construct()
{
$this->creationDate = new \Datetime();
$this->modificationDate = new \Datetime();
}
// Get and set
}
However, When a user subscribe on the website, I create a default album called Upload that I want to keep in the user class.
This is what I tried to do :
/**
* User
*
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToOne(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album", cascade={"persist"})
*/
protected $albumUpload;
// Get and set
}
I have this error :
Undefined index: album in /Users/Sandro/sites/moodress-website/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 1608. This error appears directly when I serialize any entity that has a user object...
The error is caused by the association annotation of the $albumUpload property in the User class.
Doctrine assumes that you have a $album property in your Album entity when you use a #ORM\OneToOne(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album") association in your User entity.
Try
/**
** #ORM\ManyToOne(targetEntity="Moodress\Bundle\UserBundle\Entity\User", inversedBy="albums")
** #ORM\JoinColumn(nullable=false)
*/
private $user;
in your Album entity and
/**
* #ORM\OneToMany(targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album", mappedBy="user", cascade={"persist"})
*/
protected $albums;
in your User entity. In addition please add $this->albums = new ArrayCollection() to User::__construct().
Now if you want to add and keep a default album for users you should implement this somewhere in your business logic. You could figure out a way to identify the default album in your collection of albums and prevent deletion especially for this item.
Hope this helps.
My error:
'Undefined index: album'
results from this annotation in the Album class.
/**
* #ORM\OneToMany(
* targetEntity="Moodress\Bundle\AlbumBundle\Entity\Picture",
* cascade={"persist"},
* mappedBy="album"
* )
*/
I have set mappedBy to album but there is no $album property in my Picture class.
I did add this to my Picture class and clear my cache.
/**
* #ORM\ManyToOne(
* targetEntity="Moodress\Bundle\AlbumBundle\Entity\Album",
* inversedBy="pictures"
* )
*/
protected $album;
It solved my problem