i edit the thread for put more info.
I have the "User" entity and the "Rol" entity, and i am fighting to do work the collection of Roles of a User.
In the User entity i defined:
/**
* #ManyToMany(targetEntity="AppsManantiales\CommonBundle\Entity\Perfil")
* #JoinTable(name="usuarios_perfiles",
* joinColumns={#JoinColumn(name="idUsuario", referencedColumnName="idusuario")},
* inverseJoinColumns={#JoinColumn(name="idPerfil", referencedColumnName="idperfil")}
* )
*/
protected $perfiles;
And in the constructor:
public function __construct(){
$this->perfiles = new \Doctrine\Common\Collections\ArrayCollection();
$this->contacto = new \Doctrine\Common\Collections\ArrayCollection();
}
Before the class namespace put:
use AppsManantiales\CommonBundle\Entity\Perfil;
When execute:
php app/console generate:doctrine:entities CommonBundle
An error appear:
[Doctrine\Common\Annotations\AnnotationException]
[Semantical Error] The annotation "#ManyToMany" in property AppsManantiales\CommonBundle\Entity\Usuario::$perfiles was never impo
rted. Did you maybe forget to add a "use" statement for this annotation?
Any ideas ?.
First part: So in this case, u got a relation many-to-many between Role entity and User entity. First of all, check, r entities correct after generting. Here u can find examples of establishing different realtions: http://docs.doctrine-project.org/en/latest/reference/association-mapping.html && http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html (the second has more information with examples of Doctrine queries)
Second part of your question: after establishing right relations, select query of your User gonna be smth like:
$user = $em->createQueryBuilder()
->select('u, r')
->from('YourBundle:User', 'u')
->innerJoin('u.roles', 'r')
->where('u.id IN (:ids)')
->setParameter('ids', $ids)
->getQuery()
->getResult();
And as u guess, u can get roles with the help of your accessor: $user->getRoles()
p.s. yes, ofcource if all entities r correct, u can add methods manually.
EDITED
Oh sry, I forgot, u use Symfony2. So by default in your entities, u got such line:
use Doctrine\ORM\Mapping as ORM;
As u can notice, all annotations u used were with prefix #ORM\. exmpls:
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
So just add prefix #ORM and the result:
/**
* #ORM\ManyToMany(targetEntity="AppsManantiales\CommonBundle\Entity\Perfil")
* #ORM\JoinTable(name="usuarios_perfiles",
* joinColumns={#ORM\JoinColumn(name="idUsuario", referencedColumnName="idusuario")},
* inverseJoinColumns={#ORM\JoinColumn(name="idPerfil", referencedColumnName="idperfil")}
* )
*/
Related
My Entity class:
use Doctrine\ORM\Mapping as ORM;
/**
* CustomerEntity
* #ORM\Entity
* #ORM\Table(name="customers")
* #ORM\Table(uniqueConstraints={
* #ORM\UniqueConstraint(name="email", columns={"email"}),
* })
* #ORM\Entity(repositoryClass="Customer\V1\Rest\Customer\CustomerRepository")
*/
class CustomerEntity
{
But when I am adding a customer it throws this error, it is looking for the wrong table.
SQLSTATE[42S02]: Base table or view not found: 1146 Table
'database.customerentity' doesn't exist
I did try with this, but doesn't help:
#ORM\Table(name="`customers`")
Schema generation shows this:
$ doctrine-module orm:schema-tool:update --dump-sql
The following SQL statements will be executed:
CREATE TABLE CustomerEntity (id VARCHAR(36) NOT NULL,
.....
What am I doing wrong?
I have cleared the cache too
orm:clear-cache:metadata
orm:clear-cache:query
orm:clear-cache:result
The problem you have is, that Doctrine expects each Annotation only once. Try this:
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="customers", uniqueConstraints={
* #ORM\UniqueConstraint(name="email", columns={"email"}),
* })
* #ORM\Entity(repositoryClass="Customer\V1\Rest\Customer\CustomerRepository")
*/
class CustomerEntity
{
This is really frustrating, after going through ORM core codes, I was able to pinpoint the problem. Don't have time to investigate further to verify the bug or this being a feature (normal behaviour).
By inserting #ORM\Table(name="customers") below uniqueConstraints, ORM is able to recognize the table name.
use Doctrine\ORM\Mapping as ORM;
/**
* CustomerEntity
* #ORM\Entity
* #ORM\Table(uniqueConstraints={
* #ORM\UniqueConstraint(name="email", columns={"email"}),
* })
* #ORM\Table(name="customers")
* #ORM\Entity(repositoryClass="Customer\V1\Rest\Customer\CustomerRepository")
*/
class CustomerEntity
{
I have Zend Framework 3 + Doctrine ORM application.
Class Goods have link "characters":
/**
* Goods
*
* #ORM\Entity
* #ORM\Table(name="goods")
* #property int $id
*/
class Goods implements InputFilterAwareInterface
{
/**
* #ORM\ManyToMany(targetEntity="\Application\Entity\CharacterValue", inversedBy="goods")
* #ORM\JoinTable(name="character_value_item",
* joinColumns={#ORM\JoinColumn(name="good_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="value_id", referencedColumnName="id")})
**/
protected $characters;
public function getCharacters()
{
return $this->characters;
}
}
I trying to use this method to get characters by method for lazy loading, but it returns just one character. Not all characters for the product.
$dql = 'SELECT u, ch FROM Goods u LEFT JOIN u.characters ch';
This method from here:
$query = $em->createQuery('SELECT u, p FROM CmsUser u JOIN u.phonenumbers p');
$users = $query->getResult(); // array of CmsUser objects with the phonenumbers association loaded
$phonenumbers = $users[0]->getPhonenumbers();
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/dql-doctrine-query-language.html#dql-select-examples
I do not understand why documentation's method working wrong. What is the right way to deside my issue?
I'm developping an application with symfony 3.4. I want to execute a specific query. So i have two entities: the first is PrPurchaseRequest. the second is PrSpecificFieldValue. PrPurchaseRequest has oneToMany prSpecificFieldValues.
I want to get id of purchaseRequest and prSpecificFieldValues
i did that
$queryBuilder = $this->getEntityManager()->createQuery('select p.id as purchaseId, pr.keyField AS keyField,pr.ID AS prkeyvalueid from '.PrPurchaseRequest::class. ' p LEFT JOIN '. PrSpecificFieldValue::class .' spec ON p.id = spec.purchaseId ');
and that didn't work for me
[Syntax Error] Error: Expected end of string, got
'ON'
how can i do it
Using doctrine you need to play around your entities and their mappings with other entities in order to relate them like
use Doctrine\Common\Collections\ArrayCollection;
/** #Entity */
class PrPurchaseRequest
{
/**
*
* #OneToMany(targetEntity="PrSpecificFieldValue", mappedBy="prPurchaseRequest")
*/
private $prSpecificFieldValues;
// ...
public function __construct() {
$this->prSpecificFieldValues = new ArrayCollection();
}
}
/** #Entity */
class PrSpecificFieldValue
{
/**
*
* #ManyToOne(targetEntity="PrPurchaseRequest", inversedBy="prSpecificFieldValues")
* #JoinColumn(name="pr_purchase_request_id", referencedColumnName="id")
*/
private $prPurchaseRequest;
}
Now you have defined relationship between your entities you can join them based on their mapping (prSpecificFieldValues defined on PrPurchaseRequest class ) like
Its DQL (DQL != SQL)
SELECT p,v
FROM PrPurchaseRequest p
JOIN p.prSpecificFieldValues v
No need to specify ON clause doctrine will handle this for you.
One-To-Many, Bidirectional
I have a Customer entity and User entity with a JOIN relationship table customers_users.
In the Customer entity I have this.
/**
* #var User
*
* #ORM\ManyToMany(targetEntity="Entity\User")
* #ORM\JoinTable(name="customers_users",
* joinColumns={#ORM\JoinColumn(name="customer_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", unique=true)}
* )
*
*/
private $users;
I want that when a customer is created I can assign the users to it and actually it works well, however I want filter the users to show only those that don't are assigned to none customer.
For example, I have two customers and two users and the first customer has assigned two users; then when I edit the second customer, two users appear to be assigned to it but when I select these and I send the form, it throws the following exception:
An exception occurred while executing 'INSERT INTO customers_users (customer_id, user_id) VALUES (?, ?)' with params [2, 1]:
SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "uniq_2763c6cca76ed395"
DETAIL: Key (user_id)=(1) already exists.
/**
* #var User
*
* #ORM\ManyToMany(targetEntity="Entity\User", inversedBy="customers")
* #ORM\JoinTable(name="customers_users",
* joinColumns={#ORM\JoinColumn(name="customer_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", unique=true)}
* )
*
*/
private $users;
and in the User entity, in customers annotation you should put:
* #ORM\ManyToMany(targetEntity="Entity\Customer", inversedBy="users")
(...)
What I actually did in this situation, is:
// UserAdmin.php that extends SonataAdminBundle's User admin
/**
* {#inheritdoc}
*/
public function createQuery($context = 'list')
{
/** #var QueryBuilder $query */
$query = parent::createQuery();
$request = Request::createFromGlobals();
// Could not find another way to detect that admin list is created from
// sonata_type_model_list parent.
// Of course, this applies only to sonata_type_model_list field type.
if ($request->query->get('pcode') == 'demo.admin.customer') {
$alias = $query->getRootAliases()[0];
$query->leftJoin($alias . '.customers', 'c');
// $query-> ... do filtering here
}
return $query;
}
This way I could filter Users in any way I wanted.
I hava relations Many-to-Many with Product entity and Feature entity
Product entity:
/**
* #ORM\ManyToMany(targetEntity="Feature")
* #ORM\JoinTable(name="Product_Feature",
* joinColumns={#ORM\JoinColumn(name="Product_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="Feature_id", referencedColumnName="id")}
* )
*/
private $features;
Feature entity:
/**
* #ORM\ManyToMany(targetEntity="Product", mappedBy="features")
* #ORM\OrderBy({"position" = "ASC"})
*/
private $products;
ProductRepository.php:
public function updateFeatures($id, $featuresIds)
{
return $this->getEntityManager()->createQueryBuilder()
->update('TestCatalogBundle:Product', 'p')
->set('p.features', ':features')
->where('p.id = :id')
->setParameter('features', $featuresIds)
->setParameter('id', $id)
->getQuery()
->getResult();
}
But when I call updateFeatures I get error:
features = :features': Error: Invalid PathExpression.
StateFieldPathExpression or SingleValuedAssociationField expected
How can I update Product_Feature table? Also I can't delete all features from Product_Feature by product's id.
I changed my controller in next way:
$em = $this->getDoctrine()->getEntityManager();
$features = $em->getRepository('TestCatalogBundle:Feature')->findBy(array('id' => $featureIds));
$product = $em->getRepository('TestCatalogBundle:Product')->find($id);
$product->getFeatures()->clear();
foreach ($features as $feature) {
$product->addFeature($feature);
}
$em->persist($product);
$em->flush();
But if I use native sql I need 2 queries for deleting features and insert new features. But here I need 2 select queries. Maybe I made this task wrong?
You're doing it the wrong way. You should read this chapter of the documentation: Working with associations. You should add an "inversedBy" keyword in the $features field of the Product class.
When you have a bi-directional many-to-many relation, the usual way to do this is:
$product->getFeatures()->add($feature); // Or $product->setFeatures($features);
$feature->getProducts()->add($product);
$em->persist($product);
$em->persist($feature);
$em->flush();