Doctrine ManyToOne relation with compositeKey - php

I have 2 entities let's say company and address they are related like this:
class Company
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="NONE")
* #ORM\Column(type="string", length=20, name="company_id")
* #Groups({"read", "write"})
*/
private $id;
/**
* #ORM\Column(type="string", length=20, name="group_id")
* #Groups({"read", "write"})
*/
private $groupId;
/**
* #ORM\ManyToOne(targetEntity=Address::class, inversedBy="company")
* #ORM\JoinColumns(
* {
* #ORM\JoinColumn(nullable=true, referencedColumnName="address_id", name="address_id"),
* #ORM\JoinColumn(nullable=true, referencedColumnName="group_id", name="group_id")
*
* })
* #Groups({"read", "write"})
*/
private $address;
class Address
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="NONE")
* #ORM\Column(type="string", length=20, name="address_id")
* #Groups({"read", "write"})
*/
private $id;
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="NONE")
* #ORM\Column(type="integer", name="group_id")
*/
private $groupId;
the problem I'm encountering is when I don't provide something for relation in Company::$address I'll get group_id = null even when I try to set it in various ways.
I found the line which is responsible for setting it to null vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:704
For now, I resolved it by adding a second column, company_group_id, but I was wondering if there is a better way to do this

Related

Doctrine Associations in symfony

so I have been working with Symfony for a while but there is one thing that bothers.
It's about Doctrine Associations.
The thing is that I am trying to achieve a user friend invites and relations and there is a page that the user can see the invitations he sent and the ones that are pending.
EDIT: I made it happen using Many-To-One/One-To-Many associations. However
My question is - Are Doctrine Associations the correct way of doing that.
My User Entity
class User implements UserInterface
{
private $id;
/**
* #ORM\Column(name="first_name", type="string", length=30)
*
* #Assert\NotBlank(message="First name cannot be a blank field", groups={"register"})
* #Assert\Length(min="3", max="30", groups={"register"})
*/
/**
* #ORM\Column(type="string", length=50)
*
* #Assert\NotBlank(message="Username cannot be a blank field", groups={"register"})
* #Assert\Length(min="7", max="50", groups={"register"})
*/
private $username;
/**
* #ORM\Column(type="string", length=255)
*
* #Assert\Length(min="7", max="50", groups={"register"})
*/
private $password;
/**
* #ORM\OneToMany(targetEntity="App\Entity\UserInvitation", mappedBy="inviterId", orphanRemoval=true)
*/
private $userInvitations;
/**
* #ORM\OneToMany(targetEntity="App\Entity\UserInvitation", mappedBy="invitedId", orphanRemoval=true)
*/
private $pendingUserInvitations;
//getters and setters
My UserInvitation Entity
class UserInvitation
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="userInvitations")
* #ORM\JoinColumn(name="inviter_id", nullable=false)
*/
private $inviterId;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="pendingUserInvitations")
* #ORM\JoinColumn(name="invited_id", nullable=false)
*/
private $invitedId;
/**
* #ORM\Column(type="boolean")
*/
private $status;
This is my database.
The relationships is the right way to do it although on the entity I would use the following:
class UserInvitation
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="userInvitations")
* #ORM\JoinColumn(name="inviter_id", nullable=false)
*/
private $inviter;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="pendingUserInvitations")
* #ORM\JoinColumn(name="invited_id", nullable=false)
*/
private $invitee;
/**
* #ORM\Column(type="boolean")
*/
private $status;
Then you would getInviter() or setInviter(). Basically think that you are saving the related object to the entity and not the related field

OrderFilter (Sorting) by Virtual Property API-Platform

class SingleProduct extends AbstractEntity implements SingleProductEntityInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({"read", "get"})
*/
private $id;
/**
* #var string
* #ORM\Column(name="name", type="string", length=255, nullable=true)
* #Groups({"read", "get"})
*/
private $name;
/**
* #ORM\Column(name="main_han", type="string", length=20, nullable=true)
* #Groups({"read","get"})
*/
private $mainHan;
/**
* #ORM\Column(name="main_ean", type="string", length=13, nullable=true)
* #Groups({"read","get"})
*/
private $mainEan;
/**
* #Groups({"read","get"})
*/
private $nbCatalogs;
}
In this entity, I am taking count of relational entity in getter of nbCatalogs. Other above fields are columns in database. when I added
#ApiFilter(OrderFilter::class, properties={"id", "name","mainHan","mainEan","nbCatalogs"}, arguments={"orderParameterName"="order"})
I am able to sort asc and desc by id,name,mainHan,mainEan but I am not able to sort by virtual property which I created 'nbCatalogs'.
How can I achieve sorting by property nbCatalogs??

doctrine mapping for self referencing class attribute

I have a Forum Entity that may contain sub forums which will be of the same class(Forum) . i am having trouble with establishing this relation .
the code below is what i have tried so far in my Forum class
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255, nullable=false)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=5000, nullable=false)
*/
private $description;
/**
* #ORM\Column(type="string")
*
* #Assert\NotBlank(message="Please, upload the forum wallpaper as a PNG file.")
* #Assert\File(mimeTypes={ "image/png" })
*/
private $wallpaper;
/**
* #var \DateTime
*
* #ORM\Column(name="added_date", type="datetime", nullable=false)
*/
private $addedDate;
/**
* #var array
*
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\User", cascade={"remove"})
*/
private $moderators;
/**
* #var Forum[]
* #ORM\OneToMany(targetEntity="Forum", mappedBy="id", cascade={"all"}, orphanRemoval=true)
*/
private $subForums;
/**
* #var \AppBundle\Entity\User
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $userId;
the problem after updating the database scheme i didnt end up with any table linkin forums and subforums so i am confused how can i add a sub forum to an exsiting forum later on . Any help is much appriciated
I believe what you are looking for is a One-To-Many self-referencing mapping
So change your $subForums like so:
/**
* #var Forum[]
* #ORM\OneToMany(targetEntity="Forum", mappedBy="parentForum", cascade={"all"}, orphanRemoval=true)
*/
private $subForums;
and add $parentForum, like so:
/**
* #ManyToOne(targetEntity="Forum", inversedBy="subForums")
* #JoinColumn(name="parent_id", referencedColumnName="id")
*/
private $parentForum;

Can't Create association on Symfony2

I'm trying to create a "OneToMany" bidirectional association in my project but when I execute "doctrine:schema:update" nothing happens.
If I create this association directly from Sequel Pro and run the update schema command, that changes dissapear... :/
The relations is:
- One "id" from Customers Table with many "customer_id" form Control table.
Here is the Customers code:
<?php
namespace Ourentec\CustomersBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Customers
*
* #ORM\Table()
* #ORM\Entity
*/
class Customers
{
/* #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=100)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="lastname", type="string", length=100)
*/
private $lastname;
/**
* #var string
*
* #ORM\Column(name="address", type="text")
*/
private $address;
/**
* #var string
*
* #ORM\Column(name="phone", type="string", length=100)
*/
private $phone;
/**
* #var string
*
* #ORM\Column(name="pass", type="string", length=100)
*/
private $pass;
/**
* #var string
*
* #ORM\Column(name="tasks", type="text")
*/
private $tasks;
/**
* #var string
*
* #ORM\Column(name="status", type="string", length=100)
*/
private $status;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=100)
*/
private $email;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* #var string
*
* #ORM\Column(name="location", type="string", length=100)
*/
private $location;
/**
* #ORM\OneToMany(targetEntity="Control", mappedBy="customers")
*/
private $customer_id;
public function __construct()
{
$this->customer_id = new ArrayCollection();
}
And the Control code:
<?php
namespace Ourentec\CustomersBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Control
*
* #ORM\Table()
* #ORM\Entity
*/
class Control
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="customer_id", type="integer")
*
* #ORM\ManyToOne(targetEntity="Customers", inversedBy="control")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
*/
private $customerId;
/**
* #var integer
*
* #ORM\Column(name="user_id", type="integer")
*/
private $userId;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* #var integer
*
* #ORM\Column(name="seen", type="smallint")
*/
private $seen;
I followed the documentation from this 2 websites
http://symfony.com/doc/current/book/doctrine.html
http://librosweb.es/libro/symfony_2_x/capitulo_8/relaciones_y_asociaciones_de_entidades.html
But I don't know why it does not work..
Any idea will be appreciated :)
Mapping are not correct, I will try to explain how it works.
In Customers entity (you should rename it to Customer, entites names are singular)
/**
* #ORM\OneToMany(targetEntity="Control", mappedBy="customer")
*/
private $controls;
Mapped by option defines field name in the other entity.
/**
* #var integer
*
* #ORM\Column(name="customer_id", type="integer")
*
* #ORM\ManyToOne(targetEntity="Customers", inversedBy="controls")
* #ORM\JoinColumn(name="customer_id", referencedColumnName="id")
*/
private $customer;
Same thing with inversedBy.
In Customers entity you also need to init controls var as an ArrayCollection:
public function __construct()
{
$this->controls = new ArrayCollection();
}
With these mappings schema should be updated correctly.
For more info, check doctrine docs.

Doctrine - ManyToOne with table between

I want to create model which will have table users with reference to table CustomFieldValue nad table CustomField with reference to CustomFieldValue too. CustomFieldValue will have only id, value and two columns, one from users and second from CustomField. I want to have functionality like a dynamic adding a new fields in registration form. Is this good idea? If yes, please help me with this model, because it doesn't work:
User:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(type="string", length=64)
*/
private $password;
/**
* #ORM\ManyToMany(targetEntity="Role", inversedBy="users",cascade={"persist"})
*
*/
private $roles;
/**
* #ORM\Column(type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\Column(type="string", length=60)
*/
private $sex;
/**
* #ORM\ManyToMany(targetEntity="Region", inversedBy="users")
* #ORM\JoinColumn(name="region", referencedColumnName="id")
*/
private $region;
/**
* #ORM\ManyToMany(targetEntity="Type", inversedBy="users")
* #ORM\JoinColumn(name="type", referencedColumnName="id")
*/
private $type;
/**
* #ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToOne(targetEntity="CustomFieldValue",inversedBy="id")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $customValues;
CustomFieldValue:
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="value", type="string", length=255)
*/
private $value;
/**
*ORM\OneToMany(targetEntity="User", mapped-by="id")
*#ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
*#ORM\OneToMany(targetEntity="CustomField", mapped-by="id" )
*#ORM\JoinColumn(name="field_id", referencedColumnName="id")
*/
private $field;
CustomField:
/**
* #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)
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="type", type="string", length=255)
*/
private $type;
/**
* #var boolean
*
* #ORM\Column(name="required", type="boolean")
*/
private $required;
/**
* #ORM\ManyToOne(targetEntity="CustomFieldValue", inversedBy="id")
* #ORM\JoinColumn(name="customfield_id", referencedColumnName="id")
*/
private $customValues;
Your mapping is a little off:
User Entity Should Be:
/**
* #ORM\ManyToOne(targetEntity="CustomFieldValue", inversedBy="user")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $customValues;
CustomFieldValue Should Be:
/**
*ORM\OneToMany(targetEntity="User", mappedBy="customValues")
*/
private $user;
/**
*#ORM\OneToMany(targetEntity="CustomField", mappedBy="customValues" )
*/
private $field;
CustomField should be:
/**
* #ORM\ManyToOne(targetEntity="CustomFieldValue", inversedBy="field")
* #ORM\JoinColumn(name="customfield_id", referencedColumnName="id")
*/
private $customValues;
You dont need the join columns when you are calling the mappedBy this already tells doctrine to look for the join column declaration on that field. For the mappedBy and inversedBy fields these are the fields that link the 2 together NOT the actual join column name.

Categories