Doctrine Refactor entities - php

Hello i am using Doctrine ORM, i have major problem. Overall i have 10 tables, each table has it's own address fields(street, city, state, zip). So basically i am trying to refactor db structure, and created one new address table with those fields, old tables will hold address_id as a reference, and i will remove address fields from each table, and migrate data.
Since it's very big project with large code base trying to determine whats the best approach to do this refactoring regarding entities.
Things to concern
find() method
findBy() method
persist
Query Builder
Here it's my userCreditCard entity, it has address object in it, and that object should be replaced with "address_id".
class UserCreditCard extends LoggableEntity implements UserCreditCardInterface
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var int|null
*
* #ORM\Column(name="user_id", type="integer", nullable=true)
*/
protected $userId;
/**
* #var string
*
* #ORM\Column(name="cc_number", type="string", length=255, nullable=false)
*/
protected $ccNumber;
/**
* #var string
*
* #ORM\Column(name="cc_name", type="string", length=255, nullable=false)
*/
protected $ccName = '';
/**
* #var \DateTime
*
* #ORM\Column(name="cc_date", type="date", nullable=false)
*/
protected $ccDate;
/**
* #var bool
*
* #ORM\Column(name="bill_addr_type", type="boolean", nullable=false)
*/
protected $billAddrType = false;
/**
* #var UserBillingAddress
* #ORM\Embedded(class = "\Cae\User\Dal\Entity\Embeddable\UserBillingAddress", columnPrefix=false)
*/
protected $address;
Here is address object.
/** #ORM\Embeddable */
class UserBillingAddress extends AbstractAddressEmbeddable
{
/**
* #var string
*
* #ORM\Column(name="bill_street_address", type="string", length=255, nullable=false)
*/
protected $address = '';
/**
* #var string
*
* #ORM\Column(name="bill_street_address2", type="string", length=255, nullable=false)
*/
protected $address2 = '';
/**
* #var string
*
* #ORM\Column(name="bill_city", type="string", length=255, nullable=false)
*/
protected $city = '';
My question would be since it's very large project is it possible to some how override with entity listeners or with magic setter so for example when someone do
$this->userCreditCardRepository->find($id);
pull address data from new Address table (i can't do joins since address table lives in another module, so i have to use public services).
Maybe to override find, findBy and other methods in AbstractRepository, but i am not sure what the best approach? Any idea is appreciated.

Related

Doctrine OneToMany Relation based on entityUid field

i'me working on a project with alot of the entities have string uid LIKE ENTITY.XXXX.
I'm seaching a way to relate some entities using doctrine annotations.
In particular the entity Media that contains all the links to the media files, to other entities becouse the relations between Media and the other entities like Document, Building etc is based on a field entityUid inside the Media entity, so the field entityUid is promiscuous becouse can contain the uid form different other entities.
I realize that cannot do a reverse mapping becouse i cant populate correctoy the reversed entity becouse is promiscuous, what i'm trying to do is a direct relation between for example Document 1:n Media based on Document.uid 1:n Media.entityUid and Bulding 1:n Media based on Document.uid 1:n Media.entityUid.
I write the entities:
class Media(){
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
*/
private $id;
/**
* #var string
* #ORM\Column(name="entityUid", type="string", nullable=false)
*/
private $entityUid;
/**
* #var string
*
* #ORM\Column(name="link", type="string", nullable=true)
*/
private $link;
... other stuff.
}
class Document(){
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
*/
private $id;
/**
*#var Media[]
*
*/
private $medias;
/**
* #var string
* #ORM\Column(name="uid", type="string", nullable=false)
*/
protected $uid;
... other stuff
}
class Building(){
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
*/
private $id;
/**
*#var Media[]
*
*/
private $medias;
/**
* #var string
* #ORM\Column(name="uid", type="string", nullable=false)
*/
protected $uid;
... other stuff
}
The problem is on the definition on the relation OneToMany, based not form the id fiels but uid fileds.
I was not able to find a correct annotation to create an unidirection OneToMany relation without creating a support table like a ManyToMany document_media , building_media, that would make useless the entities uids.
Tx for your time.

Symfony3 class inheritance and db relationships

I have these 3 entitites
Users.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Users
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UsersRepository")
*/
class Users
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, unique=true)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=20)
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="phone", type="string", length=20)
*/
private $phone;
/**
* #var string
*
* #ORM\Column(name="type", type="string")
*/
private $type;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var int
*
* #ORM\Column(name="feedback", type="integer")
*/
private $feedback;
/**
* #var string
*
* #ORM\Column(name="picture", type="blob")
*/
private $picture;
/**
* #var int
*
* #ORM\Column(name="rating", type="integer", length=255)
*/
private $rating;
/**
* #var string
*
* #ORM\Column(name="info", type="text")
*/
private $info;
/**
* #var \DateTime
*
* #ORM\Column(name="datecreated", type="datetime")
*/
private $datecreated;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
}
client.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* client
*
* #ORM\Table(name="client")
* #ORM\Entity(repositoryClass="AppBundle\Repository\clientRepository")
*/
class client extends Users
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var int
*
* #ORM\Column(name="numberofjobsposted", type="integer")
*/
private $numberofjobsposted;
/**
* #var string
*
* #ORM\Column(name="clienttype", type="string", length=255)
*/
private $clienttype;
}
sprovider.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* sprovider
*
* #ORM\Table(name="sprovider")
* #ORM\Entity(repositoryClass="AppBundle\Repository\sproviderRepository")
*/
class sprovider extends Users
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var array
*
* #ORM\Column(name="interestedin", type="simple_array")
*/
private $interestedin;
/**
* #var int
*
* #ORM\Column(name="numofsuccjobs", type="integer")
*/
private $numofsuccjobs;
/**
* #var string
*
* #ORM\Column(name="sprovidertype", type="string", length=255)
*/
private $sprovidertype;
/**
* #var string
*
* #ORM\Column(name="address", type="string", length=255)
*/
private $address;
/**
* #var string
*
* #ORM\Column(name="postcode", type="string", length=255)
*/
private $postcode;
}
So I achieved that the extends statement provides the Users properties in the client and sprovider tables in MySQL. That's awesome. What I want now is to make the relations so that when I add a new client for example, both the tables Users and client add a new user/client in MySQL, and they have same id too.
the type() property in the Users entity i would like to be optional for the type of user I create. Example : I create a new client and in the Users table in MySQL the type is set to "CLIENT".
I read this and so far I think it has to be ManyToMany relation but It's quite confusing to me.
How to make those relations in the entities and then how to use them in the controller? If possible, please provide an example.
I think you're confused about the reasons to use inheritance.
The idea is that you have base class, in this case User, and that can be extended to provide variations of that class, in this case client (you should capitalise this) and sprovider.
Ideally, you would not have a User table, only the other 2.
In doctrine, this is called a mapped super-class.
A mapped superclass is an abstract or concrete class that provides persistent entity state and mapping information for its subclasses, but which is not itself an entity. Typically, the purpose of such a mapped superclass is to define state and mapping information that is common to multiple entity classes.
see the documentation here
you can link properties using relationships, this is their example.
<?php
/** #MappedSuperclass */
class MappedSuperclassBase
{
/** #Column(type="integer") */
protected $mapped1;
/** #Column(type="string") */
protected $mapped2;
/**
* #OneToOne(targetEntity="MappedSuperclassRelated1")
* #JoinColumn(name="related1_id", referencedColumnName="id")
*/
protected $mappedRelated1;
// ... more fields and methods
}
/** #Entity */
class EntitySubClass extends MappedSuperclassBase
{
/** #Id #Column(type="integer") */
private $id;
/** #Column(type="string") */
private $name;
// ... more fields and methods
}

Optional ManyToOne relationship in Doctrine 2

I'm building an application for SNMP Trap logging. It has two MySQL tables: one with the traps, and one with the hosts that I want to log.
The traps table is filled externally. The hosts can be entered through the website. A host CAN have one or many traps. A trap CAN have one host.
So this is a many to one relationship, but optional on both sides. How do I implement this, since Doctrine requires for one of the members to be a primary key, and therefore not nullable?
Code for both classes:
class Trap
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="eventname", type="string", length=50)
*/
private $eventname;
/**
* #var string
*
* #ORM\Column(name="eventid", type="string", length=50)
*/
private $eventid;
/**
* #var string
*
* #ORM\Column(name="trapoid", type="string", length=100)
*/
private $trapoid;
/**
* #var string
*
* #ORM\Column(name="enterprise", type="string", length=100)
*/
private $enterprise;
/**
* #var string
*
* #ORM\Column(name="community", type="string", length=20)
*/
private $community;
/**
* #var string
*
* #ORM\Column(name="hostname", type="string", length=255)
*/
private $hostname;
/**
* #var string
*
* #ORM\Column(name="agentip", type="string", length=16)
*/
private $agentip;
/**
* #var string
*
* #ORM\Column(name="category", type="string", length=20)
*/
private $category;
/**
* #var string
*
* #ORM\Column(name="severity", type="string", length=255)
*/
private $severity;
/**
* #var string
*
* #ORM\Column(name="uptime", type="string", length=20)
*/
private $uptime;
/**
* #var datetime
*
* #ORM\Column(name="traptime", type="datetime")
*/
private $traptime;
/**
* #var string
*
* #ORM\Column(name="formatline", type="string", length=255)
*/
private $formatline;
/**
* #ORM\ManyToOne(targetEntity="Host", inversedBy="traps")
* #ORM\JoinColumn(name="agentip", referencedColumnName="ip", nullable=true)
*/
protected $host;
}
class Host
{
/**
* #var string
* #ORM\Id
* #ORM\Column(name="ip", type="string", length=16)
*/
private $ip;
/**
* #ORM\Column(name="hostname", type="string", length=100)
*/
private $hostname;
/**
* #ORM\Column(name="type", type="string", length=100)
*/
private $type;
/**
* #ORM\Column(name="importance", type="integer", length=1)
*/
private $importance;
/**
* #ORM\OneToMany(targetEntity="Trap", mappedBy="host")
*/
protected $traps;
}
Edited with error
The error is that I'm not allowed to delete or truncate my hosts table, which should be possible in my application, because traps must be able to exist without a host.
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`snmptt`.`snmptt`, CONSTRAINT `FK_9BF059B998B5BE9E` FOREIGN KEY (`agentip`) REFERENCES `hosts` (`ip`))
Posted as answer from comment as believe to be appropriate answer;
"If you are trying to remove this as straight sequel then yes the error is correct you cannot remove the parent before unlink the child, if there is no parent then this is fine if so unlink first then remove"

Symfony2 Relationship entities + forms

I'm trying to write one form for submitting against MySQL DB, but I can't get it working, I've tried a lot of things (separate forms, create an ->add('foo', new foo()) to a field, and trying to parse plain SQL with a normal HTML form is my only solution, which is obviously not the best.
This is my DB structure:
![enter image description here][1]
As you can see I need to insert the comments textarea to ticketcomments among the user who wrote it, etc.
On crmentity the description field.
Then on ticketcf the fields that I need to submit from form, are this (because you wont know if I don't tell you because of the field names):
tcf.cf594 AS Type,
tcf.cf675 AS Suscription,
tcf.cf770 AS ID_PRODUCT,
tcf.cf746 AS NotificationDate,
tcf.cf747 AS ResponseDate,
tcf.cf748 AS ResolutionDate,
And, of course, every table needs to have the same ticketid id for the submitted form, so we can retrieve it with one simple query.
It will be easy to do with plain SQL instead of using DQL and Symfony2 forms, but is not a good way to do it.
EDIT
This is my new created entity Ticket.php, which has relations to the tables above... if someone could check it out and tell me if it's okay...
ticket.php
<?php
namespace WbsGo\clientsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* VtigerTicketcomments
*
* #ORM\Table(name="vtiger_troubletickets")
* #ORM\Entity(repositoryClass="WbsGo\clientsBundle\Entity\TicketsRepository")
*/
class Tickets
{
/**
* #var \WbsGo\clientsBundle\Entity\VtigerCrmentity
*
* #ORM\OneToOne(targetEntity="WbsGo\clientsBundle\Entity\VtigerCrmentity")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="ticketid", referencedColumnName="crmid", unique=true)
* })
* #ORM\Id
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="ticket_no", type="string", length=100, nullable=false)
*
*/
private $ticketNo;
/**
* #var string
*
* #ORM\Column(name="groupname", type="string", length=100, nullable=true)
*/
private $groupName;
/**
* #ORM\ManyToOne(targetEntity="VtigerContactdetails")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="parent_id", referencedColumnName="contactid", unique=true)
* })
*/
private $parentId;
/**
* #ORM\ManyToOne(targetEntity="VtigerAssets")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="product_id", referencedColumnName="assetsid", unique=true)
* })
*/
private $productId;
/**
* #var string
*
* #ORM\Column(name="priority", type="string", length=100, nullable=true)
*/
private $priority;
/**
* #var string
*
* #ORM\Column(name="severity", type="string", length=100, nullable=true)
*/
private $severity;
/**
* #var string
*
* #ORM\Column(name="status", type="string", length=100, nullable=true)
*/
private $status;
/**
* #var string
*
* #ORM\Column(name="category", type="string", length=100, nullable=true)
*/
private $category;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255, nullable=true)
*/
private $title;
/**
* #var text
*
* #ORM\Column(name="solution", type="text", nullable=true)
*/
private $solution;
/**
* #var text
*
* #ORM\Column(name="update_log", type="text", nullable=true)
*/
private $updateLog;
/**
* #var integer
*
* #ORM\Column(name="version_id", type="integer", nullable=true)
*/
private $versionId;
/**
* #var string
*
* #ORM\Column(name="hours", type="string", length=255, nullable=true)
*/
private $hours;
/**
* #var string
*
* #ORM\Column(name="days", type="string", length=255, nullable=true)
*/
private $days;
/**
* #var integer
*
* #ORM\Column(name="from_portal", type="integer", nullable=true)
*/
private $fromPortal;
/**
* #ORM\OneToMany(targetEntity="VtigerTicketcomments", mappedBy="ticketid")
*
*/
protected $comments;
/**
* #ORM\OneToOne(targetEntity="VtigerTicketcf", mappedBy="id")
*/
protected $ticketcf;
/**
* #ORM\OneToOne(targetEntity="VtigerCrmentity", mappedBy="crmid")
*/
protected $crmtable;
}
VtigerTicketcf.php
<?php
namespace WbsGo\clientsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* VtigerTicketcf
*
* #ORM\Table(name="vtiger_ticketcf")
* #ORM\Entity
*/
class VtigerTicketcf
{
/**
* #var string
*
* #ORM\Column(name="cf_546", type="string", length=255, nullable=true)
*/
private $cf546;
/**
* #var string
*
* #ORM\Column(name="cf_556", type="string", length=255, nullable=true)
*/
private $cf556;
/**
* #var string
*
* #ORM\Column(name="cf_589", type="string", length=3, nullable=true)
*/
private $cf589;
/**
* #var string
*
* #ORM\Column(name="cf_590", type="string", length=3, nullable=true)
*/
private $cf590;
/**
* #var string
*
* #ORM\Column(name="cf_592", type="string", length=100, nullable=true)
*/
private $cf592;
/**
* #var string
*
* #ORM\Column(name="cf_593", type="string", length=255, nullable=true)
*/
private $cf593;
/**
* #var string
*
* #ORM\Column(name="cf_594", type="string", length=255, nullable=true)
*/
private $cf594;
/**
* #var string
*
* #ORM\Column(name="cf_675", type="string", length=50, nullable=true)
*/
private $cf675;
/**
* #var float
*
* #ORM\Column(name="cf_689", type="decimal", nullable=true)
*/
private $cf689;
/**
* #var float
*
* #ORM\Column(name="cf_690", type="decimal", nullable=true)
*/
private $cf690;
/**
* #var float
*
* #ORM\Column(name="cf_691", type="decimal", nullable=true)
*/
private $cf691;
/**
* #var float
*
* #ORM\Column(name="cf_693", type="decimal", nullable=true)
*/
private $cf693;
/**
* #var string
*
* #ORM\Column(name="cf_746", type="string", length=50, nullable=true)
*/
private $cf746;
/**
* #var string
*
* #ORM\Column(name="cf_747", type="string", length=50, nullable=true)
*/
private $cf747;
/**
* #var string
*
* #ORM\Column(name="cf_748", type="string", length=50, nullable=true)
*/
private $cf748;
/**
* #var string
*
* #ORM\Column(name="cf_761", type="string", length=255, nullable=true)
*/
private $cf761;
/**
* #var string
*
* #ORM\Column(name="cf_763", type="string", length=255, nullable=true)
*/
private $cf763;
/**
* #var string
*
* #ORM\Column(name="cf_764", type="string", length=255, nullable=true)
*/
private $cf764;
/**
* #var string
*
* #ORM\Column(name="cf_765", type="string", length=255, nullable=true)
*/
private $cf765;
/**
* #var string
*
* #ORM\Column(name="cf_770", type="string", length=50, nullable=true)
*/
private $cf770;
/**
* #var \WbsGo\clientsBundle\Entity\Tickets
* #ORM\Id
* #ORM\OneToOne(targetEntity="WbsGo\clientsBundle\Entity\Tickets")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="ticketid", referencedColumnName="ticketid", unique=true)
* })
*
*/
private $id;
}
VtigerTicketcomments.php
<?php
namespace WbsGo\clientsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* VtigerTicketcomments
*
* #ORM\Table(name="vtiger_ticketcomments")
* #ORM\Entity
*/
class VtigerTicketcomments
{
/**
* #var string
*
* #ORM\Column(name="comments", type="text", nullable=true)
*/
private $comments;
/**
* #var integer
*
* #ORM\Column(name="ownerid", type="integer", nullable=false)
*/
private $ownerid;
/**
* #var string
*
* #ORM\Column(name="ownertype", type="string", length=10, nullable=true)
*/
private $ownertype;
/**
* #var \DateTime
*
* #ORM\Column(name="createdtime", type="datetime", nullable=false)
*/
private $createdtime;
/**
* #var integer
*
* #ORM\Column(name="commentid", type="integer")
* #ORM\Id
*/
private $id;
/**
* #var \WbsGo\clientsBundle\Entity\Tickets
* #ORM\OneToOne(targetEntity="WbsGo\clientsBundle\Entity\Tickets")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="ticketid", referencedColumnName="ticketid", unique=true)
* })
*
*/
private $ticketid;
}
VtigerCrmentity.php
<?php
namespace WbsGo\clientsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* VtigerCrmentity
*
* #ORM\Table(name="vtiger_crmentity")
* #ORM\Entity
*/
class VtigerCrmentity
{
/**
* #var integer
*
* #ORM\Column(name="smcreatorid", type="integer", nullable=false)
*/
private $smcreatorid;
/**
* #var integer
*
* #ORM\Column(name="smownerid", type="integer", nullable=false)
*/
private $smownerid;
/**
* #var integer
*
* #ORM\Column(name="modifiedby", type="integer", nullable=false)
*/
private $modifiedby;
/**
* #var string
*
* #ORM\Column(name="setype", type="string", length=30, nullable=false)
*/
private $setype;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="createdtime", type="datetime", nullable=false)
*/
private $createdtime;
/**
* #var \DateTime
*
* #ORM\Column(name="modifiedtime", type="datetime", nullable=false)
*/
private $modifiedtime;
/**
* #var \DateTime
*
* #ORM\Column(name="viewedtime", type="datetime", nullable=true)
*/
private $viewedtime;
/**
* #var string
*
* #ORM\Column(name="status", type="string", length=50, nullable=true)
*/
private $status;
/**
* #var integer
*
* #ORM\Column(name="version", type="integer", nullable=false)
*/
private $version;
/**
* #var integer
*
* #ORM\Column(name="presence", type="integer", nullable=true)
*/
private $presence;
/**
* #var integer
*
* #ORM\Column(name="deleted", type="integer", nullable=false)
*/
private $deleted;
/**
* #var integer
*
* #ORM\Column(name="crmid", type="integer")
* #ORM\Id
*/
private $crmid;
}
And this is my repository method...
public function findByIdAndCustomerId($id) {
$query = $this->getEntityManager()
->createQuery(
'
SELECT
IDENTITY(t.id) AS id,
t.ticketNo AS Ticket,
t.title AS Asunto,
t.status AS Estado,
t.updateLog AS LOG,
t.hours AS Horas,
t.solution AS Solucion,
t.priority AS Prioridad,
tcf.cf748 AS F_Reso,
tcf.cf747 AS F_Resp,
tcf.cf746 AS F_Noti,
tcf.cf770 AS IDPROD,
tcf.cf594 AS Tipo,
tcf.cf675 AS Suscripcion,
c.comments AS Comments,
CONCAT (CONCAT(s.firstname, \' \'), s.lastname) AS Contacto
FROM WbsGoclientsBundle:Tickets t
JOIN t.parentId s
JOIN t.ticketcf tcf
JOIN t.comments c
WHERE t.ticketNo = :ticketNo
')
->setParameter('ticketNo', $id)
;
try {
//return $query->getSingleResult();
return $query->getResult();
}
catch (\Doctrine\ORM\NoResultException $e)
{
return null;
}
}
I can retrieve an array of X ticket even if I just search by ONE ID, because if ID1 has 4comments, then I got 4 same tickets, one per comment... How can I make it only ONE ticket with comments => array(...) so I can iterate inside that comments array inside twig?
And also VtigerCrmentity.Description doesn't work either, it returns this error...
Notice: Undefined index: crmid in
/var/www/wbsgo/dev.wbsgo/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php
line 826
I don't have getter and setter because I'm re-generating them again, if annotation are OK, the entities will update correctly with get/set and my forms will be able to submit using relationships, right?
You may embed a form that does represent an underlying entity field by setting mapped option to false, e.g.:
->add('comments', 'collection', array(
'type' => new VtigerTicketcommentsType(),
'mapped' => false
))
However, be careful when assigning form data, since $form->submit($data) will not set data to underlying collection of comment objects. You'll need to process them manually inside the controller. You may access the data that has been flagged as non-mapped using $form->getExtraData() after the data is submitted to the form.
If you'd like Symfony to automatically set data to comments, you'll need to construct a relationship between VtigerTroubletickets and VtigerTicketcomments entities, which, according to the question title, you don't have and try to avoid.
Edit:
A form type is bound to a given entity class. By default, each field you add to a form type must have an underlying property in a declared entity class (or getter/setter pair if property is not defined public). When you construct a form object from form type (OpenTicketType) and data (new VtigerTroubletickets()):
$form = $this->createForm(new OpenTicketType(), new VtigerTroubletickets());
the form get bounds with data present in the object you just created. The object does not have comments property, even more, the form itself knows the field is not mapped and it will not try to populate it from the object, so naturally the collection is rendered as empty, as no data about comments was passed.
To get past this, you may pass array of data instead of newly created object (note: the values may be empty, however comments array must have length > 0 - the comment has to exist, though without actual data).
[
"title" => "...",
"priority" => "...",
"solution" => "...",
"comments" => [
0 => [/* comment 0 data */],
1 => [/* comment 1 data */],
.......
]
]
This is the form creation. When the form is POST-ed, there is one additional step beside constructing the form. The request data has to be bound onto form, so you do $form->submit($request). Now the form AND underlying entity object will get populated with fresh data.
The $form->getExtraData() is simply a method for accessing the data that form holds and is not mapped to an underlying object - which comments field is, since we flagged it as such.
Alternatively to using getExtraData - extracting data from form manually - you may add a property comments to VtigerTroubletickets entity with getters/setters and not mark it as a db column. That way, you may remove the mapped => false option at form type, and form will automatically read/populate comments property.
Still, when persisting, these comments will not be considered for storing, so you'll have to handle them manually. Likewise, when fetching an object from database, the comments property would be empty, so prior to creating a form, you'd have to add some comments to an object, e.g.:
$tickets = new VtigerTroubletickets();
$tickets->setComments(....);
$form = $this->createForm(new OpenTicketType(), $tickets);
I think #usoban has taken you most of the way. Think of these as two long comments as opposed to answers.
It seems you have a ticket entity and a comment entity with a 1 to many relationship between them but you don't want to actually establish a formal relationship between them because the "DB is used by another platform"? What exactly does that mean. Are you sharing php code with another application? Are you using doctrine 2? With Doctrine 2 you can establish the relationship without changing the actual database.
You really should look at adding a getComments to your ticket entity. It will make your S2 life much easier.
This answer is built on what #usoban said about using an array but takes a slightly different approach.
// In the controller
$formData = array();
$formData['ticket'] = new Ticket(),
$formData['comments'] = array(new Comment(), new Comment());
$form = $this->createForm(new TicketCommentsType(), $formData);
$form->handleRequest($request);
if ($form->isValid())
{
$formData = $form->getData();
$ticket = $formData['ticket'];
$comments = $formData['comments'];
// Persist ticket
// Persist comments
TicketCommentsFormType simply brings the two different entities into one form.
class TicketCommentsFormType
public function buildForm(
$builder->add('ticket',new OpenTicketType());
$builder->add('comments','collection',array(
'type' => new VtigerTicketcommentsType()
With this approach there is no need to have any direct relation between Ticket and Comment.
I've found the way to do it, and the problems.
The relations are this:
crmentity.id > Main, this table has not relationships
troubleticket.ticketid > This one has relation with crmentity.id
ticketcf.ticketid > this one has relation with troubleticket.ticketid
So the order when you insert needs to be crmentity->troubleticket->ticketcf
But in Symfony2, when you make forms, you must create the last table element as the first form to be generated, so I'll post my code in case someone has the same problem as me.
http://pastebin.com/wLPyXvbj
:)

Why are my Symfony/Doctrine2 entites different from my CI/D2 ones ? (Ultimately, What is the difference between Doctrine 2 and Doctrine 2 ORM ?)

I know this seems like a very basic question but PLEASE before voting down, read until the end.
This question came to my mind when using Codeigniter along with Doctrine 2.
I have noticed that, at least when using annotation, the synthax is slightly different than when using Doctrine 2 with Symfony2 and I am wondering why.
I'll provide an example:
This is a class in Symfony2 with a Many To One relation:
<?php
namespace Pondip\LakeBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* Lake
*
* #ORM\Table(name="pondip_lake")
* #ORM\Entity(repositoryClass="Pondip\LakeBundle\Entity\LakeRepository")
*/
class Lake
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
* #Assert\Type(type="Pondip\LakeBundle\Entity\Venue")
*
* #ORM\ManyToOne(targetEntity="Pondip\LakeBundle\Entity\Venue")
* #ORM\JoinColumn(name="venue_id", referencedColumnName="id")
*/
private $venue;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #var text
*
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="Pondip\UserAccountBundle\Entity\User")
* #ORM\JoinColumn(name="created_by", referencedColumnName="id", nullable=true)
*/
private $createdBy;
please pay attention to all the #ORM\ everywhere.
Now, when using this with codeigniter2/Doctrine2.3.0 I have Mapping errors in my console.
But, when following some tuts, I ended up removing all of the ORM\ (and the corresponding use Doctrine\ORM\Mapping as ORM) and it worked.
This work :
<?php
namespace Entity;
/**
* Friend Model
*
* #Entity
* #Table(name="friend")
* #author Miles Yohann Merran <hello_miles#hotmail.com>
*/
class Friend
{
/**
* #Id
* #Column(type="integer", nullable=false)
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Column(type="string", length=32, unique=true, nullable=false)
*/
protected $name;
/**
* #Column(type="text", nullable=false)
*/
protected $description;
/**
* #Column(type="string", length=64, nullable=false)
*/
protected $picture;
/**
* #Column(type="string", length=64, nullable=false)
*/
protected $genre;
/**
* #ManyToOne(targetEntity="User", inversedBy="friends")
* #JoinColumn(nullable=false)
*/
protected $user;
/**
* #var datetime $date
*
* #Column(name="date", type="datetime")
*/
protected $date;
When this doesn't work (pay attention at the ORM)
<?php
namespace Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Friend Model
*
* #Entity
* #Table(name="friend")
* #author Miles Yohann Merran <hello_miles#hotmail.com>
*/
class Friend
{
/**
* #Id
* #Column(type="integer", nullable=false)
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Column(type="string", length=32, unique=true, nullable=false)
*/
protected $name;
/**
* #Column(type="text", nullable=false)
*/
protected $description;
/**
* #Column(type="string", length=64, nullable=false)
*/
protected $picture;
/**
* #Column(type="string", length=64, nullable=false)
*/
protected $genre;
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="friends")
* #ORM\JoinColumn(nullable=false)
*/
protected $user;
/**
* #var datetime $date
*
* #ORM\Column(name="date", type="datetime")
*/
protected $date;
Why ? What is the difference ?
EDIT: To be exact, I tried 2 entites, with the same structure, one with #ORM\ before avery annotation sentence, and one without. The one with #ORM\ wasn't managed properly by Doctrine 2 when using the terminal commands and the one without works perfectly well. I wasn't able to find any documentation about that even if I clearly see both in the doc and the src that there is Doctrine Common, Doctrine ORM and Doctrine DBAL. Aren't they compatible between each other ? how to properly manage this difference ? especially when working with another framework than S (like CI2)
Thank you
Long story short, in symfony the doctrine annotation reader is an AnnotationReader, whereas in CI using the doctrine Setup::createAnnotationMetadataConfiguration helper, you have the SimpleAnnotationReader by default.
You should be able to have the same behavior as in symfony by passing false to the 5th argument $useSimpleAnnotationReader of Setup::createAnnotationMetadataConfiguration.

Categories