Mysql relationship between tables - php

I have a question to now what is the best solution to make relations between tables:
I have :
client table with id name sector_id delegation_id
sector table with id name
delegation table with id name sector_id
My question is that is it a good practice to have both foreign keys in the client table or just the key of delegation_id is sufficient for indexing and searching in the client table (of course with join tables)
to explain more
each delegation belongs to a sector.
each sector belongs to a zone
and each Client belongs to a delegation that belongs to a sector that is grouped in a geographical area
this is my Entity files :
Class client
class Client {
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="firstName", type="string", length=255)
*/
private $firstName;
/**
* #var string
*
* #ORM\Column(name="lastName", type="string", length=255)
*/
private $lastName;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, unique=true)
*/
private $email;
/**
* #var string
*
* #ORM\Column(name="sector", type="string", length=255)
*/
private $sector;
/**
* #var int
*
* #ORM\Column(name="delegation", type="integer")
*/
private $delegation;
}
Class sector
class Sector {
/**
* #ORM\Id
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Delegation" ,mappedBy="sector")
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #Assert\NotBlank()
* #ORM\Column(type="string")
*/
private $name;
/**
* #Assert\NotBlank()
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Zone", inversedBy="id")
* #ORM\JoinColumn(nullable=false)
*/
private $zone;
}
class Delegation
class Delegation {
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Sector", inversedBy="id" )
* #ORM\JoinColumn(nullable=false)
*/
private $sector;
}

Based on your updated question -
If each Client belongs to a Delegation, the Client entity should have a delegation_id foreign key.
If each Delegation belongs to a Sector, the Delegation entity should have a sector_id foreign key.
And if each Sector belongs to a Zone, the Sector entity should have a zone_id foreign key.
You would therefore remove your sector_id foreign key from your Client entity, and use the relationship through the Delegation entity to find all Client entities within a given Sector, if this were ever required.

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.

How to constrain saving id number as a value of field in ManyToOne Doctrine relation?

I have ManyToOne relation defined below.
Persisting owning side object, with inversed object setted in there, resulting in saving row in db of owning side where column that I expect to have value of id foreign key (integer) instead it save name (string) field of inversed table side.
In other words:
column iptra_documents.document_category_id contains value from iptra_document_category.name. I'm expecting to have iptra_document_category.id value in iptra_documents.document_category_id
Owning side:
/**
* #ORM\Table(name="iptra_documents")
*/
class IptraDocuments
{
/**
* #var int
*
* #ORM\Column(name="document_id", type="integer", unique=true)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $documentId;
/**
* #var IptraDocumentCategory
* #ORM\Column(name="document_category_id")
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\IptraDocumentCategory", inversedBy="id")})
*/
private $documentCategory;
//.....
public function setCategory(IptraDocumentCategory $documentCategory)
{
$this->documentCategory = $documentCategory;
}
Inverse side:
/**
* #ORM\Entity
* #ORM\Table(name="iptra_document_category")
*/
class IptraDocumentCategory
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id", type="integer")
*/
private $id;
/**
* #ORM\Column(name="parent_id", type="integer")
*/
private $parentId;
/**
* #ORM\Column(name="name", type="string")
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\IptraDocuments", mappedBy="documentCategory")
*/
private $iptraDocuments;
According to the docs, you don't need #ORM\Column but #ORM\JoinColumn to define "Many" side
/**
* #var IptraDocumentCategory
*
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\IptraDocumentCategory", inversedBy="id")})
*/
private $documentCategory;

unique_base option of sluggable exention doesn't accept a foreign key

I have entity Store and entity Category and each Store can add his own categories.
I'd like to generate an unique Slug for each Category based on foreign key store_id. I tried using "unique_base" option but it doesn't work.
Why the "unique_base" option of Sluggable extension does not accept a foreign key ?
class Category
{
/**
* #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;
/**
* #Gedmo\slug(fields={"name"}, unique_base="store")
* #ORM\Column(name="slug",length=255, unique=false)
*/
private $slug ;
/**
* #ORM\ManyToOne(targetEntity="Project\StoreBundle\Entity\Store", inversedBy="categories", cascade={"persist"})
* #ORM\JoinColumn(nullable=true)
*/
private $store ;
//.................
}
Looking at the Sluggable Docs you need to use RelativeSlugHandler: to handle foreign-keys

Symfony 2 relations issue

I nead help.
I have 3 entities. Book, Category And BookCategory - book can have multiple categories so i used another table.
I can easily acces Book and Category useing BookCategory table but i dont know how to do this by Book->BookCategory->Category.
class Category
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="text")
*/
private $name;
/**
* #var Category
* #ORM\ManyToOne(targetEntity="Category", inversedBy="Category")
* #ORM\JoinColumn(name="parent", referencedColumnName="id")
*/
private $parent;
class BookCategory
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Book
* #ORM\ManyToOne(targetEntity="Book", inversedBy="BookCategory")
* #ORM\JoinColumn(name="book_id", referencedColumnName="id")
*/
private $bookId;
/**
* #var Category
* #ORM\ManyToOne(targetEntity="Category", inversedBy="BookCategory")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $categoryId;
/**
* #var integer
*
* #ORM\Column(name="priority", type="integer")
*/
private $priority;
class Book
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="text")
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="author", type="text")
*/
private $author;
/**
* #var float
*
* #ORM\Column(name="price", type="float")
*/
private $price;
How i need to config my entities or how to make my DQL to achive wanted results?
With your code, you only established the relationship from BookCategory to Book. As you said, that enables you to get the Book associated to one BookCategory.
To go the other way and get all BookCategory that belong to one book, you also need to specify this relationship. What you want is a OneToMany relationship from Book to BookCategory.
<?php
//...
use Doctrine\ORM\Mapping\OneToMany;
class Book
{
//...
/**
* #OneToMany(targetEntity="BookCategory", mappedBy="bookId")
*/
private $bookCategories;
//...
}
class BookCategory
{
//...
/**
* #var Book
* #ORM\ManyToOne(targetEntity="Book", inversedBy="bookCategories")
* #ORM\JoinColumn(name="book_id", referencedColumnName="id")
*/
private $bookId;
//...
}
After adding the necessary getters and setters, getBookCategories() will give you an Array with all BookCategory that belong to the Book.
For more details, have a look at the official Symfony2 documentation:
http://symfony.com/doc/current/book/doctrine.html#relationship-mapping-metadata
Edit:
Included use statement. Corrected inversedBy property for bookId.

Inversed foreign key doctrine

i have a OneToOne relation between my entity User and UserMeta
i would like to have access to UserMeta in User but set the foreign key in the UserMeta table in my mysql database:
class User implements UserInterface{
/**
* #ORM\Column(type="integer", unique=true)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\UserMeta", cascade={"persist"}, inversedBy="id_user")
* #ORM\JoinColumn(nullable=true)
* #ORM\Column(name="id_pro")
*/
private $proData;
}
class UserMeta{
/**
* #ORM\Column(type="integer", unique=true)
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\User", mappedBy="id_pro")
* #ORM\JoinColumn(nullable=true)
* #ORM\Column(name="id_user")
*/
private $user;
}
Anyway to do that with doctrine ? I think i misunderstood mapped and inversed properties.
You mapping configuration is wrong.
In your User Class, it should read:
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\UserMeta", cascade={"persist"}, inversedBy="user")
* #ORM\JoinColumn(nullable=true)
*/
private $proData;
and in your UserMeta Class, it should read:
/**
* #ORM\OneToOne(targetEntity="Foo\Bar\Entity\User", mappedBy="proData")
* #ORM\JoinColumn(nullable=true)
*/
private $user;
You also don't need the #ORM\Column directive since Doctrine2 will automatically do it for you.

Categories