8


I have many relations of this type, but I can't see why this one is not working.
I have a Delegation and a Promotion entities:
Delegation

Promotion

    /**
 * Company\CBundle\Entity\Promotion
 * 
 * @ORM\Entity
 * @DoctrineAssert\UniqueEntity("promotionCode")
 */
class Promotion
{
    const REGISTER_DAYS = 30;
    const REGISTER_DISCOUNT = 100;

    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(name="promotionCode", type="string", unique=true, nullable=true)
     */
    protected $promotionCode;

    /**
     * @ORM\Column(name="name", type="string")
     */
    protected $name;

    /**
     * @ORM\Column(name="description", type="string", nullable=true)
     */
    protected $description;

    /**
     * @ORM\Column(name="days", type="integer")
     */
    protected $days;

    /**
     * @ORM\Column(name="discount", type="float")
     */
    protected $discount;

    /**
     * @ORM\ManyToOne(targetEntity="Delegation", inversedBy="promotions")
     * @ORM\JoinColumn(name="delegation_id", referencedColumnName="id")
     */
    private $delegation;

    /**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="promotions")
     */
    private $product;

    /**
     * @var date $adquiredDate
     *
     * @ORM\Column(name="adquiredDate", type="date", nullable=true)
     */
    private $adquiredDate;

When in a controller I create a promotion, the table Promotion has the new object related to the delegation one

private function createPromotion($delegation)
{
    $em = $this->getDoctrine()->getEntityManager();
    $promotion = Promotion::createPromotion($delegacion, Promotion::REGISTER_DAYS, Promotion::REGISTER_DISCOUNT);
    $em->persist($promotion);
    $em->persist($delegation);

    $em->flush();
}

Database

*************************** 15. row ***************************
           id: 32
delegation_id: 19
         days: 20
     discount: 50
 adquiredDate: 2013-01-10

*************************** 16. row ***************************
           id: 33
delegation_id: 19
         days: 25
     discount: 50
 adquiredDate: 2013-01-10
*************************** 17. row ***************************
           id: 34
delegation_id: 19
         days: 30
     discount: 50
 adquiredDate: 2013-01-10

But when I call the $delegation->getPromotions() in another controller/action there is no promotions, returns a Doctrine\ORM\PersistentCollection with no data.

Can anyone help, please?


Edit with more information. $delegation->getPromotions() is empty, but looking for a promotion of that delegation and calling $promotion->getDelegation() is returning the delegation correctly :?

hosseio
  • 1,142
  • 2
  • 12
  • 25
  • Why are you using a static function to create your entities? The `__construct` function is there for a reason. – Squazic Jan 10 '13 at 16:16
  • Dependency injection. I only use it for it, when not I use the __construct function as well :) – hosseio Jan 10 '13 at 16:33

2 Answers2

5

Have you tried defining your $delegation property like

/**
 * @ORM\ManyToOne(targetEntity="Delegation", inversedBy="promotions")
 * @ORM\JoinColumn(name="delegation_id", referencedColumnName="id")
 */
private $delegation;

See Doctrine2 Docs: Association Mapping->Many-To-One


Also there are a lot of typos in your code. For example

/**
 * @ORM\OneToMany(targetEntity="Promotion", mappedBy="delegacion", cascade={"all"}, orphanRemoval=true)
 */
protected $promotions;

mappedBy="delegacion" should be mappedBy="delegation".

Or

public function getDeleTacion()
{
    return $this->deleTacion;
}

Should be

public function getDelegation()
{
    return $this->delegation;
}

Edit

Okay, I created a minimalistic version for you that worked for me. You can built it up from there or watch for differences with your code:

Promotion.php

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Promotion
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Delegation", inversedBy="promotions", cascade={"persist"})
     * @ORM\JoinColumn(name="delegation_id", referencedColumnName="id")
     */
    public $delegation;

    /**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="promotions", cascade={"persist"})
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
     */
    public $product;
}

Delegation.php

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Delegation
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="Promotion", mappedBy="delegation", cascade={"all"}, orphanRemoval=true)
     */
    public $promotions;

    public function __construct() {
        $this->promotions = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

Product.php

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Product
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="Promotion", mappedBy="product", cascade={"all"}, orphanRemoval=true)
     */
    public $promotions;

    public function __construct() {
        $this->promotions = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

If you now do something like

$delegation = new Delegation();
$product = new Product();
$promotion = new Promotion();
$promotion->delegation = $delegation;
$promotion->product = $product;

$em->persist($promotion);
$em->flush();

$products = $em->createQuery('select p from BundleName\Entity\Product p')->execute();
$delegations = $em->createQuery('select d from BundleName\Entity\Delegation d')->execute();

var_dump(count($products[0]->promotions), count($delegations[0]->promotions));

You should end up with

int(1)
int(1)

So the refrence is in fact saved and can be read. Phew. Good luck with that! :-)

flu
  • 14,307
  • 8
  • 74
  • 71
  • Thank you for your help. I have already tried using the joincolumn annotation, and I have the same problem.About the typos, I'm sorry, I'm spanish and translate "delegacion" to "delegation" and "promocion" to "promotion" only here, but there is no typos in my code.Thanks – hosseio Jan 10 '13 at 16:27
  • I don't know. It may be a problem having more OneToMany relations in Delegation entity? – hosseio Jan 10 '13 at 16:29
  • 1
    I only see one ;-) Please post your Delegation and Promotion classes (just the property definitions not the methods) so I can have a look at them. – flu Jan 10 '13 at 16:32
  • Sure, sorry then about the spanish, I'm editing the original post. – hosseio Jan 10 '13 at 16:34
  • 1
    I created a basic implementation of your three classes and ran a check on them. Updated my post accordingly. – flu Jan 10 '13 at 17:33
  • Yes, as you indicate the reference is saved and can be read. I guess I'm going to use dql for this, but I don't want to. Even the reference can be read there is no way to read with the getPromotions() method, and don't know why. At any rate, thank you for your help :) – hosseio Jan 10 '13 at 17:46
  • 1
    getPromotions() is no magic method. It should simply return the `promotions` property of the product or delegation and thus if you add it to my code you can write `count($products[0]->getPromotions())`. If you don't want to use DQL use a repository class instead. I just wanted to spare me the overhead of creating them too. But at some point you need to get your Product or Delegation entity out of the DB after writing the corresponding Promotion!? You have to use a repository class or DQL. I don't see where your current problem is? Help me out :) – flu Jan 10 '13 at 17:51
  • oh yes, you are right, I didn't read that correctly. I apologize, I'm really tired because of this. – hosseio Jan 10 '13 at 17:55
  • 1
    I edited my last comment. Don't know if that's promoted to you but I think your answer was to the version from before. – flu Jan 10 '13 at 18:08
  • This one is ok. Finally I detected the real problem, but no fix it. $delegation->promotions->count() returns the number correctly, but $delegation->promotions is a PersistenCollection with no data! EDIT: In fact, if I ask for the count first then the collection is loaded, if I don't the collection is empty. It sounds to be a lazy load problem? – hosseio Jan 11 '13 at 08:59
  • 1
    Yes, that's correct. Doctrine2 uses Proxy classes for lazy loading almost everywhere. But acessing $delegation->promotions should automatically invoke the corresponding fetch. But it doesn't for you? – flu Jan 11 '13 at 10:44
  • Yes, I just see it too. I was going crazy. a var_dump($delegation->promotions) get a empty persistentCollection, but using it there is no problem. Thanks for everything. – hosseio Jan 11 '13 at 10:47
5

I had a similar error where my many-to-one relationship on some freshly created entities contained entities, and an inverse one-to-many didn't, although database clearly had the corresponding rows in it.

I did persist and flush entities on the one-to-many side, but I had to also do 

$entityManager->clear();

before getting those entities from a repository again for the one-to-many relationship to be able to access those entities.

gvlasov
  • 18,638
  • 21
  • 74
  • 110