Doctrine2: What is wrong with the association between these entities? - doctrine

I am trying to work through simple examples to see all the changes in Doctrine2.
Please take a look at the following entity snippets:
VCat.php
namespace Application\Models;
/**
* #Entity
* #Table(name="v_cat")
*/
class VCat
{
/**
* #Id #Column(type="bigint")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #OneToMany(targetEntity="VScat", mappedBy="vCat") )
*/
private $vScats;
namespace Application\Models;
VScat.php
namespace Application\Models;
/**
* #Entity
* #Table(name="v_scat",indexes={#index(name="FK_v_scat",columns={"vcatid"})})
*/
class VScat
{
/**
* #Id #Column(type="bigint")
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ManyToOne(targetEntity="VCat", inversedBy="vScats")
* #JoinColumn(name="vcatid", referencedColumnName="id")
*/
private $vCat;
vcatid is the Foreign Key column in table v_scat
This is the query I am trying to run:
$categories = Zend_Registry::get('em')
-> createQuery('select c.name, sub.name as sub_name from \Application\Models\VCat c JOIN c.VScat sub WHERE sub.active = 1 and c.active = 1 and c.id = sub.vcatid')
-> getResult();
And this is the error:
(string:130) [Semantical Error] line 0, col 69 near 'sub WHERE sub.active': Error: Class Application\Models\VCat has no association named VScat
It seems right, but I am obviously missing something.
UPDATE Now I get this error, which refers to the table column name in mysql. Is that incorrect? I thought I needed to tell Doctrine somehow that this property belongs to this field in the DB.
Error: Class Application\Models\VScat has no field or association named vcatid

It's the property on VCat you need to reference not the entity type.
JOIN c.VScat sub
should be:
JOIN c.vScats sub

Related

Symfony entity - Oracle default SYSDATE not working

Symfony 5 + Oracle.
Entity:
/**
* #var \DateTime
*
* #ORM\Column(name="CREATE_DT", type="date", nullable=false, options={"default"="SYSDATE"})
*/
private $createDt = 'SYSDATE';
Controller:
//save entity object to database (createDt property NOT passed, default must be applied)
$em->persist($obj);
$em->flush();
Error:
Could not convert PHP value 'SYSDATE' of type 'string' to type 'date'. Expected one of the following types: null, DateTime (500 Internal Server Error)
How can I make Symfony apply default SYSDATE at flush?
You can init your date with default value directly in the constructor.
class YourEntity {
/**
* #var \DateTime
*
* #ORM\Column(name="CREATE_DT", type="date", nullable=false)
*/
private $createDt;
public function __construct() {
$this->createDt = new \Datetime();
}
}

Symfony 2.8 - Oracle : ManyToMany return The column id must be mapped to a field in class

I have Two entity has ManyToMany relation between them blogPost et Category et the associative table blogPost_Category.
PS: The tables exist in the database.
So, I starting to create the entities
<?php
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\Column;
/**
*#ORM\Table(name="blogPost")
*#ORM\Entity("App\TestBundle\Repository\BlogPostRepository")
*/
class blogPost {
/**
*#Id
*Column(name="ID", type="integer", length=20, nullable=false, unique=true)
*/
private $id;
.
.
.
/**
*#ORM\ManyToMany(targetEntity="Category", inversedBy="blogPosts")
*#ORM\JoinTable(name="blogPost_Category",
*joinColumns={#ORM\JoinColumn(name="id", referencedColumnName="id")},
*inverseJoinColumns={#ORM\joinColumn(name="id", referencedColumnName="id")}
*)
*/
private $categories;
public function __construct()
{
$this->categories = new ArrayCollection();
}
public function getCategories()
{
return $this->categories;
}
.
.
.
The other Entity has the same data and structure,
And when I call for example the getCategories on the controller I get this error
The column id must be mapped to a field in class
App\TestBundle\Entity\blogPost since it is referenced by a join column
of another class.
is there any solution?
if not, Can I create entity for the associative table and use ManyToOne on the two directions?
You have multiple id reference in your join table, you do not have to specify the name if you don't want to, so you could change your ORM to :
/**
* #ORM\ManyToMany(targetEntity="Category", inversedBy="blogPosts")
* #ORM\JoinTable(name="blogPost_Category")
*/ private $categories;
And in your Category entity :
/**
* #ORM\ManyToMany(targetEntity="BlogPost", mappedBy="categories")
*/
Do not forget to update your schema.

Many-to-Many Relations using non-"id" Primary Key in Doctrine

So I'd like to create two entities and make a many-to-many reference. I would love to make this association using a string primary key on one table. This seems to be really hard, at least it took me pretty much time trying without any results yet.
This is my approach:
First entity:
namespace Project\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="User")
*/
class User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $Id;
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="Users")
* #ORM\JoinTable(name="role_user",
* joinColumns={#ORM\JoinColumn(name="User_Id", referencedColumnName="Id")},
* inverseJoinColumns={#ORM\JoinColumn(name="Role_Name", referencedColumnName="Name")}
* )
*/
private $Roles;
}
And the second:
namespace Project\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="Role")
*/
class Role
{
/**
* #ORM\Id
* #ORM\Column(type="string", length=256)
*/
private $Name;
/**
* #ORM\ManyToMany(targetEntity="User", mappedBy="Roles")
* #ORM\JoinTable(name="role_user",
* joinColumns={#ORM\JoinColumn(name="Role_Name", referencedColumnName="Name")},
* inverseJoinColumns={#ORM\JoinColumn(name="User_Id", referencedColumnName="Id")}
* )
*/
private $Users;
}
Output of ./app/console doctrine:schema:validate:
[Mapping] FAIL - The entity-class 'Project\AdminBundle\Entity\User' mapping is invalid:
* The referenced column name 'Id' has to be a primary key column on the target entity class 'Project\AdminBundle\Entity\User'.
* The referenced column name 'Id' has to be a primary key column on the target entity class 'Project\AdminBundle\Entity\Role'.
What do I miss?
Attention upper/lowercase! Doctrine generates its columns as lowercase per default. This solves the issue:
* joinColumns={#ORM\JoinColumn(name="User_Id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="Role_Name", referencedColumnName="name")}
This it over-complicated; it's enough to put this into the Role entity:
/**
* #ORM\ManyToMany(targetEntity="User", mappedBy="Roles")
* #ORM\JoinColumn(name="role_user", referencedColumnName="name")
*/
private $Users;
I only thought about this when writing the question.. what a good method to think about the problem again from scratch.
Cheers

Symfony2 - UniqueEntity no action

I have an entity named Test with two fields: id and name.
I would like to have the name as unique.
What I did:
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
...
/**
* Company\AppBundle\Entity\Test
*
* #ORM\Table(name="test")
* #UniqueEntity("name")
* #ORM\Entity(repositoryClass="Company\AppBundle\Entity\TestRepository")
*
*/
class Test
{
....
/**
* #var string$name
*
* #ORM\Column(name="name", type="string", length=200, nullable=false, unique=true)
*/
private $name;
....
In my controller, I am using:
if ($form->isValid()) {
....
But the validation goes through. Am I missing something?
The unique annotation is for doctrine, it passes it to the database level and the error gets thrown from there. It will not know that the entity exists until you try to save it. To do the checks in php you have to query for the unique attribute yourself and check if it exists...

Doctrine 2 - not able to save one to many self-reference relationship

I have a problem saving a one to many self-reference relationship, both parent and children are saved properly on the database, but Im getting parent_id null for the children.
I folloed the doctrine example ... but no idea
namespace CD\Entity;
/**
* #Entity
*/
class Category {
/**
* #Id
* #Column(type="integer")
* #GeneratedValue(strategy="IDENTITY")
*/
private $id;
/** #Column(type="string",length=50) */
private $name;
/**
* #OneToMany(targetEntity="Category", mappedBy="parent",cascade={"persist"})
*/
private $children;
/**
* #ManyToOne(targetEntity="Category", inversedBy="children")
* #JoinColumn(name="parent_id", referencedColumnName="id")
*/
private $parent;
// setters and getters ...
}
and my controller here:
public function insertAction()
{
$cm = new CD\Entity\Category();
$cc = new CD\Entity\Category();
$cm->name = 'mainCat';
$cc->name = 'childCat';
$cm->children = array($cc);
$this->_em->persist($cm);
$this->_em->flush();
}
I really dont know what im doing wrong
Have you tried out Doctrine Extensions, particularly the tree extension? It makes work like this extremely easy.
You need to persist ALL of your entities.
And after running (assuming you use doctrine)
doctrine:generate:entities CD/Entity
Your will have a function named "Category->addChildren" which should be used to add children to an existing category entity.
Try this:
public function insertAction()
{
$cm = new CD\Entity\Category();
$cc = new CD\Entity\Category();
$cm->setName('mainCat');
$cc->setName('childCat');
$cm->addChildren($cc);
$this->_em->persist($cm);
$this->_em->persist($cc);
$this->_em->flush();
}

Resources