I have the following situation:
/**
* #Entity
* #Table(name="users")
*/
class Users{
/**
*
* #Id #Column(type="integer")
* #GeneratedValue
*/
protected $id_user;
/**
* #OneToMany(targetEntity="Items",mappedBy="user")
*/
private $items;
//this method sould return distinct items by name or group by name
public function getItems(){
return $this->items;
}
}
/**
* #Entity
* #Table(name="items")
*/
class Items{
/**
*
* #Id #Column(type="integer")
* #GeneratedValue
*/
protected $id_item;
/**
*
* #Id #Column(type="string")
*/
protected $name;
/**
* #ManyToOne(targetEntity="User",inversedBy="items")
* #JoinColumn(name="id_user", referencedColumnName="id_user" ,onDelete="CASCADE")
*/
protected $user;
}
In my view i send an $UserEntity, my problem is that i want to display only items that have unique name.
So If i do $items=$userEntity->getItems(); i receive all user items, not only unique one.
How can i solve this situation?
Thanks
select distinct with DQL should do the trick
Related
I'm trying to implement a doctrine relation for a symphony 3 app.
I have two different classes, one extending from the other, which are related to the same entity with a many to one relation.
Here are my classes.
Country.php
class Country
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Groups({"exposed"})
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="Link", mappedBy="country")
*/
private $link;
/**
* #ORM\OneToMany(targetEntity="LinkChild", mappedBy="country")
*/
private $linkChild;
public function __construct()
{
$this->link = new ArrayCollection();
$this->linkChild = new ArrayCollection();
}
}
Link.php
/**
* Link
*
* #ORM\Table(name="link")
* #ORM\Entity(repositoryClass="Decathlon\AppCollaboratorBundle\Reposito\LinkRepository")
* #Vich\Uploadable
* #ORM\HasLifecycleCallbacks()
*/
class Link
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Serializer\Groups({"link_list", "link_info"})
* #Serializer\Expose()
*/
protected $id;
/**
* #var Country
*
* #ORM\ManyToOne(targetEntity="Country", inversedBy="link", cascade={"persist"})
* #JoinColumn(name="country_id", referencedColumnName="id")
*/
protected $country;
}
LinkChild.php
/**
* #ORM\Entity(repositoryClass="Decathlon\AppCollaboratorBundle\Repository\LinkChildRepository")
*/
class LinkChild extends Link
{
/**
* #var Country
*
* #ORM\ManyToOne(targetEntity="Country", inversedBy="linkChild", cascade={"persist"})
* #JoinColumn(name="country_id", referencedColumnName="id")
*/
protected $country;
}
I need to create a relation between both Link and LinkChild to Country but no country column is created in LinkChild table.
I've told not to use recursive classes so I must create Link and LinkChild.
Is there a way to acomplish what I'm tryng to do.
Thank you in advance.
I think what you are looking for is single table inheritance?
<?php
namespace MyProject\Model;
/**
* #Entity
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
*/
class Person
{
// ...
}
/**
* #Entity
*/
class Employee extends Person
{
// ...
}
Take a look here:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#single-table-inheritance
Try renaming your protected $country; variable to something like private $childCountry; to make it a variable that belongs specifically to LinkChild.
Your protected $country; override in LinkChild is ignored because it is exactly the same as the one in Link.
I got this error from my UserRepository:
[Semantical Error] line 0, col 51 near 'h': Error: Class DokMngr\Entity\User has no association named id
I understand that the error comes from the missing declaration inside my user entity. I can not find a correct syntax when a field is both a generated id and a OneToMany association.
Hope somebody can help me to solve my problem or at least explain why I can't use an id as an association.
class UserRepository extends EntityRepository
{
public function findAllwithHistoryCount() {
$qb = $this->createQueryBuilder('u')
->leftJoin('u.id', 'h');
return $qb->getQuery()->getResult();
}
}
/**
* #Entity(repositoryClass="DokMngr\Repository\UserRepository")
* #Table(name="users")
*/
class User implements UserInterface
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
}
/**
* #Entity(repositoryClass="DokMngr\Repository\HistoryRepository")
* #Table(name="history")
*/
class History
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
/**
* #ManyToOne(targetEntity="User", inversedBy="id")
* #JoinColumn(name="user", referencedColumnName="id")
*/
protected $user;
}
Thanks to Olibiaz I found my error in reasoning.
I thought the whole time that I have to create an association between User.id and History.user like inside the database.
But instead I have to create a new field histories in my User entity. (which exactly not exist inside the database)
So here's the corrected entities:
User
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity(repositoryClass="DokMngr\Repository\UserRepository")
* #Table(name="users")
*/
class User implements UserInterface
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
/**
* #OneToMany(targetEntity="History", mappedBy="user")
*/
private $histories;
}
History
/**
* #Entity(repositoryClass="DokMngr\Repository\HistoryRepository")
* #Table(name="history")
*/
class History
{
/**
* #Id
* #Column(type="integer")
* #GeneratedValue
*/
protected $id;
/**
* #ManyToOne(targetEntity="User", inversedBy="histories")
* #JoinColumn(name="user", referencedColumnName="id")
*/
protected $user;
}
I'm having trouble with a Doctrine 2 mapped superclass, to define a ManyToMany Relation.
My code is :
use Doctrine\Common\Collections\ArrayCollection;
/** #MappedSuperclass */
abstract class MyAbstractClassA
{
/**
* #Id
* #GeneratedValue
* #Column(type="integer")
* #var int
*/
protected $id;
/**
* #ManyToMany(targetEntity="MyClassE")
* #var MyClassE[]
*/
protected $my_class_es;
// ... Other fields and methods
}
/** #Entity() */
class MyConcreteClassAa extends MyAbstractClassA
{
/**
* #Column(type="string")
* #var string
*/
public $aa_param;
// ... Other fields and methods
}
/** #Entity() */
class MyConcreteClassAb extends MyAbstractClassA
{
/**
* #Column(type="string")
* #var string
*/
public $ab_param;
// ... Other fields and methods
}
/** #Entity() */
class MyClassE
{
/**
* #Id
* #Column(type="integer")
* #var int
*/
protected $id;
/**
* #Column(type="string")
* #var string
*/
protected $e_param;
/**
* #ManyToOne(targetEntity="MyClassF")
* #var MyClassF
*/
protected $my_class_f;
// ... Other fields and methods
}
/** #Entity() */
class MyClassF
{
/**
* #Id
* #Column(type="integer")
* #var int
*/
protected $id;
// ... Other fields and methods
}
So here is the schema of what i have : http://pix.toile-libre.org/upload/original/1385651287.png
And there is what i want : http://pix.toile-libre.org/upload/original/1385651300.png
I don't know how to obtain this result, could someone tell me if it's possible ?
Thank you for helping me.
I'm encountering a strange problem using Doctrine2.
I'm getting the following error:
doctrine orm:validate-schema
[Mapping] FAIL - The entity-class 'EmailVerification' mapping is invalid:
* The referenced column name 'id' does not have a corresponding field with this
column name on the class 'OurUsers'.
[Database] OK - The database schema is in sync with the mapping files.
My scenario is as follows:
I have 3 tables sharing a primary key.
Table Auth which holds user_id PK.
Table OurUsers for which Auth.user_id is shared PK.
Table EmailVerification for which OurUsers.user_id is shared PK.
I also have NotOurUsers - hence the split.
Entities are declared as follows:
/**
* #Entity
* #Table(name="auth")
*/
class Auth {
/** #Id #Column(type="integer", name="user_id") #GeneratedValue #var int */
private $id;
/* ... */
}
/**
* #Entity
* #Table(name="our_users")
*/
class OurUsers {
/**
* #Id
* #OneToOne(targetEntity="Auth")
* #JoinColumn(nullable=false, name="user_id", referencedColumnName="user_id")
* #var Auth
*/
private $id;
/* ... */
}
/**
* #Entity
* #Table(name="email_verification")
*/
class EmailVerification {
/**
* #Id
* #OneToOne(targetEntity="OurUsers")
* #JoinColumn(nullable=false, name="user_id", referencedColumnName="user_id")
* #var OurUsers
*/
private $id;
/* ... */
}
I'm using Dosctrine 2.1.
btw Doctrine 2.2 validates mappings as good, but I get same error at run time as with 2.1.
I think the problem is that EmailVerfication points to OurUSers intead of to Auth, the error message is misleading though. I am not sure the triple mapping is possible from the internals (i am pretty sure i implemented an exception for this some where as well, i have to look why this is not triggered).
You tell in your JoinColumn statements that you work with a user_id column.
But your column definition for OurUser::id creates a id column by default.
You either have to modify the JoinColumn statement to use id:
/**
* #Entity
* #Table(name="email_verification")
*/
class EmailVerification {
/**
* #Id
* #OneToOne(targetEntity="OurUsers")
* #JoinColumn(nullable=false, name="user_id", referencedColumnName="id")
* #var OurUsers
*/
private $id;
/* ... */
}
OR
add a Column annotation on OurUser::id, like that:
/**
* #Entity
* #Table(name="our_users")
*/
class OurUsers {
/**
* #Id
* #OneToOne(targetEntity="Auth")
* #Column(type="integer", name="user_id")
* #JoinColumn(nullable=false, name="user_id", referencedColumnName="user_id")
* #var Auth
*/
private $id;
/* ... */
}
I think it would be better to switch to something like this, it's a lot more clear and should create less problems:
/**
* #Entity
* #Table(name="auth")
*/
class Auth {
/** #Id #Column(type="integer", name="user_id") #GeneratedValue #var int */
private $id;
/* ... */
}
/**
* #Entity
* #Table(name="our_users")
*/
class OurUsers {
/**
* #Id
* #GeneratedValue
*/
private $id;
/**
* #OneToOne(targetEntity="Auth")
* #var Auth
*/
private $auth;
/* ... */
}
/**
* #Entity
* #Table(name="email_verification")
*/
class EmailVerification {
/**
* #Id
* #GeneratedValue
*/
private $id;
/**
* #OneToOne(targetEntity="OurUsers")
* #var OurUsers
*/
private $ourUser;
/* ... */
}
I have two classes:
User:
/** #Entity #Table(name="users") */
class User {
/**
* #Id #GeneratedValue #Column(type="integer")
* #var integer
*/
protected $id;
/**
* #Column(type="string", length=20, unique=TRUE)
* #var string
*/
protected $login;
/**
* #OneToMany(targetEntity="News", mappedBy="author")
*/
protected $news;
public function __construct() {
$this->news = new \Doctrine\Common\Collections\ArrayCollection;
}
}
and News:
/** #Entity #Table(name="news") */
class News {
/**
* #Id #GeneratedValue #Column(type="integer")
* #var integer
*/
protected $id;
/**
* #Column(type="string", length=100)
* #var string
*/
protected $title;
/**
* #Column(type="text")
* #var string
*/
protected $content;
/**
* #ManyToOne(targetEntity="User", inversedBy="news")
* #JoinColumn(referencedColumnName="id")
*/
protected $author;
}
When I will make this code
$q = $this->db->createQuery('SELECT u FROM User u WHERE u.id = '.$id);
$user = $q->getSingleResult();
does the Doctrine will download all news (created by particular user) from database?
It won't until you request a user's news by calling the news accessor method. If you rewrite your query as
SELECT u, n FROM User u JOIN u.news n
Then a user and his news will be all returned as the result.
You can also check the query generated by doctrine using a logger:
$config->setSQLLogger(new Doctrine\DBAL\Logging\EchoSQLLogger);
PS: never do this: u.id = '.$id in queries to avoid sql injections. Instead, use placeholders:
$q = $this->db->createQuery('SELECT u FROM User u WHERE u.id = :id');
$q->setParameter('id', $id);