Remove OneToOne unidirectionnal relation - symfony

I have an entity called Upload and another one called Shop
The Shop can have only one Upload
class Shop
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Upload
*
* #ORM\OneToOne(targetEntity="Vendor\SystemBundle\Entity\Upload",cascade={"all"})
*/
private $myfile;
}
class Upload
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string")
*/
private $name;
/**
* #var string $path
*
* #ORM\Column(name="path", type="string")
*/
private $path;
/**
* #var string $uniqId
*
* #ORM\Column(name="uniqId", type="string", nullable=true)
*/
private $uniqId;
/**
* #var integer $size
*
* #ORM\Column(name="size", type="integer", nullable=true)
*/
private $size;
/**
* #var string $extension
*
* #ORM\Column(name="extension", type="string", nullable=true)
*/
private $extension;
}
! Because my class Shop is generated automatically, i can't specify the relation into my class Upload
Is there a way to remove the relation and delete the corresponding item.
For now, if i want to remove my entity Upload, it says i have a Foreign Key contraint (which is normal), so I am trying to remove the relation directly from Shop, but I don't know how to do

You generated it using the php app/console doctrine:generate:entity command?
If you want to remove the relation remove the part
/**
* #var Upload
*
* #ORM\OneToOne(targetEntity="Vendor\SystemBundle\Entity\Upload",cascade={"all"})
*/
private $myfile;
and then do
php app/console doctrine:generate:entities Your\Entity\Path\
php app/console doctrine:schema:update --force
So it re-creates the getters and setters and delete the constrain from the db

Related

Symfony3 - The association refers to the owning side field which does not exist with ManyToMany and fields table

i'm trying to make a manyToMany relationship with more attributes than the ids, so I need two OneToMany relationships and two ManytoOne relationships having three tables/entities.
I have Product entity, Client entity and ProductClient entity:
class Client
{
/**
* #var integer
*
* #ORM\Column(name="id_client", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idClient;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=100, nullable=false)
*/
private $name;
/**
* #var \ProductClient
*
* #ORM\OneToMany(targetEntity="ProductClient", mappedBy="client")
*/
private $products_clients;
}
class Product
{
/**
* #var integer
*
* #ORM\Column(name="id_product", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idProduct;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=100, nullable=false)
*/
private $name;
/**
* #var \ProductClient
*
* #ORM\OneToMany(targetEntity="ProductClient", mappedBy="product")
*/
private $products_clients;
}
class ProductClient
{
/**
* #ORM\Column(name="product_id", type="integer")
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Product", inversedBy="products_clients")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id_product", nullable=false)
*/
protected $product;
/**
* #ORM\Column(name="client_id", type="integer")
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Client", inversedBy="products_clients")
* #ORM\JoinColumn(name="client_id", referencedColumnName="id_client", nullable=false)
*/
protected $client;
/**
* #var bool
*
* #ORM\Column(name="status", type="boolean")
*/
private $status;
}
That's something like this (with its getters and setters and more attributes). But symfony launches two "invalid entities errors" when I go to the Product crud:
AppBundle\Entity\Product - The association AppBundle\Entity\Product#products_clients refers to the owning side field AppBundle\Entity\ProductClient#product which is not defined as association, but as field.
AppBundle\Entity\Product - The association AppBundle\Entity\Product#products_clients refers to the owning side field AppBundle\Entity\ProductClient#product which does not exist.
And the same result if I go to the Client crud. What's wrong?
As you can see in the error message, AppBundle\Entity\ProductClient#product is not defined as association, but as field.
Just remove this #ORM\Column(name="product_id", type="integer") and this #ORM\Column(name="client_id", type="integer").
class ProductClient
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Product", inversedBy="products_clients")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id_product", nullable=false)
*/
protected $product;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Client", inversedBy="products_clients")
* #ORM\JoinColumn(name="client_id", referencedColumnName="id_client", nullable=false)
*/
protected $client;
/**
* #var bool
*
* #ORM\Column(name="status", type="boolean")
*/
private $status;
}

Doctrine2 relation for non Id column

I'm building a simple web-service using Symfony 3, Doctrine 2.5 and stuck at ORM relations described below in simplified structure.
I have an Action entity containing many actions with ManyToOne relation...
class Action
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\ManyToOne(targetEntity="\AppBundle\Entity\Status")
* #ORM\JoinColumn(referencedColumnName="code", nullable=false)
*/
private $status;
and the Status Entity with a few statuses.
class Status
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="integer", unique=true)
*/
private $code;
I cannot get proper way to set referencedColumnName="code" column (not 'Id' as usual) for Action entity.
Configured this way repo throws wxception at persist moment with "Notice: Undefined index: code";
I guess that it is mappedBy or inversedBy annotation parameter... but can't figure out "how".
Unfortunately it's not supported in Doctrine (reference).
You may edit your Status entity like this (ensure that code is set before persist):
class Status
{
/**
* #ORM\Column(name="code", type="integer", unique=true)
* #ORM\Id
*/
private $code;
}
If autoincremented field is your requirement you can take a look on this answer for possible solutions.
Just thought I'd add you can still use the non-primary keys as many to many, by using the entity itself as the join table. This will work but you still need to set your relationship keys correctly.
Example:
/**
* #ORM\Entity
*/
class Car {
/**
* #var integer
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #ORM\Column(name="registration_code", type="text", length=128, nullable=false)
* #var string
*/
public $registrationCode;
/**
* #var \Doctrine\Common\Collections\Collection
* #ORM\ManyToMany(targetEntity="Registration", mappedBy="Cars")
* #ORM\JoinTable(name="car",
* joinColumns={#ORM\JoinColumn(name="id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="registration_code", referencedColumnName="registration_code")}
* )
*/
public $Registrations;
public function __construct() {
$this->Cars = new ArrayCollection();
}
}
/**
* #ORM\Entity
*/
class Registration {
/**
* #var integer
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #ORM\Column(name="registration_code", type="text", length=128, nullable=false)
* #var string
*/
public $registrationCode;
/**
* #var ArrayCollection
* #ORM\ManyToMany(targetEntity="Car", mappedBy="Registrations")
* #ORM\JoinTable(name="car",
* joinColumns={#ORM\JoinColumn(name="registration_code", referencedColumnName="registration_code")},
* inverseJoinColumns={#ORM\JoinColumn(name="id", referencedColumnName="id")}
* )
*/
public $Cars;
public function __construct() {
$this->Cars = new ArrayCollection();
}
}
The upside is that it works fine as a workaround.
Keep in mind a few things:
it's a collection not a single instance;
column has to be managed manually on your end;
you must set up constraints correctly (indexes, keys, etc);
check your queries still perform!

symfony 2 Doctrine leftJoin NOT IN

How can I solve a query where I want to get all data from the left table which isn't existing in the right table?
left table: ID | NAME | DATE
right table: ID | ID_left_table | NAME | DATE
It is confusing me a bit since I haven't got that experience with doctrine.
My entitys look like:
class NameData
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
.
.
.
and
class ValueData
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="TestBundle\Entity\NameData")
*/
private $nameid;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
.
.
.
1) First of all, fix $nameid property annotation in ValueData entity to this:
/**
* #ORM\ManyToOne(targetEntity="NameData")
* #ORM\JoinColumn(name="name_id", referencedColumnName="id")
**/
private $nameData;
This is basic Doctrine annotation mapping for relationships, in this case ManyToOne.
2) Modify valueData table to add foreign key, by typing php app/console doctrine:schema:update --force or with migrations
3) let Symfony generate the right setters and getters for ValueData entity, by running command in your console php app/console doctrine:generate:entities TestBundle:ValueData.
4) And then, if you need to get data in controller:
$valueData = $this->getDoctrine()->getRepository('TestBundle:ValueData')->find(1);//Find by ID 1 OR ->findAll() to get all records
$nameData = $valueData->getNameData(); //This line of code behind the scenes will
//join the valueData table with nameData, and get associated data
Add a comment if you will need help along the way.
Edit:
Below is the query builder to select all NameDatas which dont have any ValueData:
$nameDataRepo = $this->getDoctrine()->getRepository('TestBundle:NameData');
$nameDatasWithoutDatavalues = $nameDataRepo->createQueryBuilder('nameData')
->leftJoin('nameData.dataValues', 'dataValue')
->where('dataValue.id IS NULL')
->getQuery()
->getResult
Also, make sure to write bi-directional part of doctrine relationships, to be able to access children from parent entity NameData.php:
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(targetEntity="ValueData", mappedBy="nameData")
*/
private $valueDatas;
/**
* Constructor
*/
public function __construct()
{
$this->valueDatas = new \Doctrine\Common\Collections\ArrayCollection();
}
And in ValueData.php, edit $nameData property annotation to this:
/**
* #ORM\ManyToOne(targetEntity="NameData", inversedBy="valueDatas")
* #ORM\JoinColumn(name="name_id", referencedColumnName="id")
**/
private $nameData;

Symfony2 Entities: Many-To-One relationship between user and posts

How can I add relationship between user and posts using users id? I saw some examples, but I couldn't follow what inversedBy and mappedBy are for... Is it possible to store profile_id and not the object?
User profile entity:
class Profiles
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
Posts/Comments entity:
class Comments
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Profiles
*
* #ORM\ManyToOne(targetEntity="Profiles")
* #ORM\JoinColumn(name="profile_id", referencedColumnName="id")
*/
private $profile;
OK example
///User Enity
/**
* #ORM\OneToMany(targetEntity="Car", mappedBy="user")
*/
private $cars;
// Car Entity
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="cars")
* #ORM\JoinColumn(name="users_id", referencedColumnName="id")
*/
private $user;
So it sill take the user id and populate this against the Car users_id column in that record
So meaning the a user can be associated to many cars

One join table for two Many-to-Many relations

I'm working on a solution for adding tags to two differente entities.
in order to get data easily in the frontend i created a joinTable named Tag_Mapping like this :
class TagMapping
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Tag", inversedBy="tags")
*/
private $tag;
/**
* #ORM\ManyToOne(targetEntity="Feed", inversedBy="tags")
*/
private $feed;
/**
* #ORM\ManyToOne(targetEntity="Question", inversedBy="tags")
*/
private $question;
...
}
The Tag Entity :
class Tag
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255, unique=true)
*/
private $name;
/**
* #Gedmo\Slug(fields={"name"})
* #ORM\Column(unique=true)
*/
private $slug;
/**
* #ORM\OneToMany(targetEntity="TagMapping", mappedBy="tag", cascade="remove")
*/
private $tags;
...
}
and in both other entities (Feed and Question) I made reference to TagMapping entity like this
...
/**
* #ORM\ManyToMany(targetEntity="Tag")
* #JoinTable(name="tag_mapping",
* joinColumns={#JoinColumn(name="feed_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="tag_id", referencedColumnName="id")}
* )
*/
private $tags;
...
the problem I'm facing is that it's not a valid way to do it, as it shows an error when i'm trying to execute :
php app/console doctrine:schema:update --force
saying that tag_mapping table already exists.
do you have any idea how can i get it done using only one joinTable instead of one for each relation ?
Thanks.

Resources