I'm trying to get a legacy database into the doctrine mappings.
All the tables have a combined primary key. One ID and one "optios id".
The problem is that Optios ID always has to be set but the OneToOne relation with the same columns causes the column "Optios ID" to be set to null. I'm not sure what I'm doing wrong or is there a way around it?
PS: The 'Pack' relation is optional.
<?php
namespace CalendarBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="CalendarBundle\Repository\CategoryRepository")
* #ORM\Table(name="Categories")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="Category_id")
*/
private $id;
/**
* #ORM\Column(type="integer", name="Optios_id")
* #ORM\Id
*/
private $optiosId;
/**
* #ORM\Column(type="string", name="Name")
*/
private $name;
/**
* #ORM\Column(type="boolean", name="AvailableOnline")
*/
private $online;
/**
* #ORM\Column(type="integer", name="SequenceNumber", nullable=true)
*/
private $order;
/**
* #ORM\Column(type="integer", name="Parent_id")
*/
private $parentId;
/**
* One Category has Many Packs.
*
* #var Pack
*
* #ORM\OneToOne(targetEntity="Pack", inversedBy="category")
* #ORM\JoinColumns(
* #ORM\JoinColumn(name="Pack_id", referencedColumnName="Pack_id"),
* #ORM\JoinColumn(name="Optios_id", referencedColumnName="Optios_id"),
* )
*/
private $pack;
/**
* #ORM\Column(type="boolean", name="Deleted")
*/
private $deleted;
Related
I am trying to add a ManyToOne column to an already existing table with rows in it.
I want it to be nullable=false!
Since it is not nullable, I'm trying to set a default value, but there is no option to do it.
If I don't set a default value, the shema update crashes and is not able to create the foreign key since there is no row with id of 0 in the table I created
The code of the table refered by the foreign key:
<?php
namespace MyBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints;
/**
* #ORM\Table(name="authority")
* #ORM\Entity()
*/
class Authority
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #Constraints\NotBlank(message="name cannot be blank.")
* #ORM\Column(type="string")
*/
protected $name;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=true)
*/
protected $createdAt;
/**
* Authority constructor.
*/
public function __construct()
{
$this->createdAt = new \DateTime();
}
}
The code of the table where I want to add the foreign key:
/**
* #var Authority
* #ORM\ManyToOne(targetEntity="MyBundle\Entity\authority", cascade={"persist"})
* #ORM\JoinColumn(referencedColumnName="id", nullable=false)
*/
protected $authority;
I tried:
protected $authority = 1;
or
* #ORM\JoinColumn(referencedColumnName="id", nullable=false, default=1)
or
public function __construct()
{
$this->authority = 1;
}
I don't want to have to change the database manually.
/**
* #var Authority
* #ORM\ManyToOne(targetEntity="MyBundle\Entity\authority", cascade={"persist"})
* #ORM\JoinColumn(referencedColumnName="id", nullable=false, columnDefinition="INT DEFAULT 1")
*/
protected $authority;
This do the trick in auto generated migration class.
You can set the default for the primary key of the referenced table. Look at the options={"default"=1}:
/**
* #ORM\Table(name="authority")
* #ORM\Entity()
*/
class Authority
{
/**
* #var int
* #ORM\Id
* #ORM\Column(type="integer", options={"default"=1})
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
#ORM\ManyToOne(targetEntity="App\Entity\Enumeration\TypeCompte")
#ORM\JoinColumn(name="IdTypeCompte", referencedColumnName="Id", nullable=false, columnDefinition="INT DEFAULT 1")
*/
private $typeCompte;
The problem I have with doctrine is that after the
php bin/console doctrine:schema:update --force
it creates the DB but not the foreign keys.
I'm using annotations and I tried to use the #ORM\JoinColumn in the ManyToOne ... etc annotations but without success.
I hope you guys can help me.
Here is the code of one of my entities:
<?PHP
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="member")
*/
class Member{
/**
* #ORM\Column(type="string",length=25)
* #ORM\Id
*/
private $code;
/**
* #ORM\Column(type="string",length=25)
*/
private $first_name;
/**
* #ORM\Column(type="string",length=25)
*/
private $last_name;
/**
* #ORM\Column(type="integer")
*/
private $national_id;
/**
* #ORM\Column(type="string",length=25)
*/
private $civil_situation;
/**
* #ORM\Column(type="string",length=1)
*/
private $gender;
/**
* #ORM\Column(type="date")
*/
private $dob;
/**
* #ORM\Column(type="integer")
*/
private $tel_mobile;
/**
* #ORM\Column(type="integer")
*/
private $tel_home;
/**
* #ORM\Column(type="integer")
*/
private $tel_ref;
/**
* #ORM\Column(type="string",length=25)
*/
private $email;
/**
* #ORM\Column(type="date")
*/
private $entry_date;
/**
* #ORM\Column(type="string",length=64)
*/
private $password;
/**
* #ORM\Column(type="integer",nullable=true)
* #ORM\OneToOne(targetEntity="Staff")
*/
private $staff;
/**
* #ORM\Column(type="integer",nullable=true)
* #ORM\OneToOne(targetEntity="Student")
*/
private $student;
/**
* #ORM\Column(type="integer")
* #ORM\ManyToOne(targetEntity="Address")
*/
private $address;
/**
* #ORM\Column(type="integer")
* #ORM\ManyToOne(targetEntity="Faculty")
*/
private $faculty;
/**
* #ORM\Column(type="integer")
*/
private $disable;
/**
* #ORM\Column(type="string",length=25,nullable=true)
*/
private $disable_reason;
/**
* #ORM\Column(type="integer",nullable=true)
*/
private $disable_year;
public function __construct()
{
//nothing
}
// getters and setters
?>
When #ORM\Column is specified along with #ORM\JoinColumn on same column, then JoinColumn's association gets ignored and Foreign Key isn't created on table. so dont use both #ORM\Column and #ORM\JoinColumn in same column.
Do like below:
/**
* #var Address
*
* #ORM\ManyToOne(targetEntity="Address")
* #ORM\JoinColumn(name="address_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $address;
It makes column named address_id on database table, with foreign key index and on deletion of Address record, associated record in dependent table is also deleted(cascade operation). You may user other operation on onDelete, see doctrine's documentation.
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
}
so, i have two entities: Genre and Game
Genre.php
<?php
namespace Acme\Bundle\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Genre
*
* #ORM\Table(name="genre")
* #ORM\Entity
*/
class Genre
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=64, nullable=false)
*/
protected $name;
/**
* #var string
*
* #ORM\Column(name="display", type="string", length=64, nullable=false)
*/
protected $display;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=false)
*/
protected $description;
/**
* #var ArrayCollection|Game[]
*
* #ORM\ManyToMany(targetEntity="Game", inversedBy="genres", cascade={"persist"})
*/
protected $games;
// ... Irrelevant Constructor and following getters/setters
}
Game.php
<?php
namespace Acme\Bundle\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Game
*
* #ORM\Table(name="game")
* #ORM\Entity
*/
class Game
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=256, nullable=false)
*/
protected $name;
/**
* #var string
*
* #ORM\Column(name="display", type="string", length=256, nullable=false)
*/
protected $display;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=false)
*/
protected $description;
/**
* #var ArrayCollection|Genre[]
*
* #ORM\ManyToMany(targetEntity="Genre", inversedBy="games", cascade={"persist"})
* #ORM\JoinTable(name="genre_game",
* joinColumns={#ORM\JoinColumn(name="genre_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="game_id", referencedColumnName="id")}
* )
*/
protected $genres;
/**
* #var ArrayCollection|Platform[]
*
* #ORM\ManyToMany(targetEntity="Platform", inversedBy="games", cascade={"persist"})
* #ORM\JoinTable(name="platform_game",
* joinColumns={#ORM\JoinColumn(name="platform_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="game_id", referencedColumnName="id")}
* )
*/
protected $platforms;
/**
* #var Image[]
*
* #ORM\OneToMany(targetEntity="Image",mappedBy="game_id", cascade={"persist"})
*/
protected $images;
}
When i run php app/console doctrine:schema:create or update, it creates all of the needed join tables I specified above, but it also creates genre_genre
This table is always empty, and doesnt seem to do anything, and prevents me from running php app/console doctrine:schema:update's later, and its trying to add an index to it that already exists
Anyone see what I'm doing wrong?
Game->genres and Genre-game are inversed by each other, which is invalid - one needs to be owning. I believe there is a doctine:schema:validate command you would find useful.
Sir, I think you have made many to many relation(bidirectional) in those mapping classes. According to doctrine documentation that will create that table for relation of those Game and Genre like in the example.
You can create the db table then create the mapper class to verify with generate-entities. This way you can verify the schema and the mapping.
I am trying to remove comments from a parent entity, I remember doing this on my last website but now it's not working..
My entity - users
namespace Application\Entities;
use Doctrine\ORM\Mapping AS ORM,
Doctrine\Common\Collections\ArrayCollection;
/**
* Loan
*
* #ORM\Table(name="users")
* #ORM\Entity
*/
class Users{
/**
* #var integer $id
*
* #ORM\Column(type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $username
*
* #ORM\Column(type="string", length=45, nullable=false)
*/
private $username;
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Comments", mappedBy="author", cascade={"persist", "remove"})
*/
private $comments;
public function getComments(){
return $this->comments;
}
and my comments table:
namespace Application\Entities;
use Doctrine\ORM\Mapping AS ORM,
Doctrine\Common\Collections\ArrayCollection;
/**
* Loan
*
* #ORM\Table(name="comments")
* #ORM\Entity
*/
class Comments{
/**
* #var integer $id
*
* #ORM\Column(type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var integer $user_id
*
* #ORM\Column(type="integer", length=15, nullable=false)
*/
private $user_id
/**
* #var Loan
*
* #ORM\ManyToOne(targetEntity="Users", inversedBy="comments",cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $author;
This is fine, it works and I get all collections called comments in the users repository..
Now, I usually do this when I need to delete:
$commentToDelete = $this->em->getRepository('Entities\Comments')->findOneById(375);
$userResults = $this->em->getRepository('Entities\Users')->findOneById(23);
$userResults->getComments()->removeElement($commentToDelete);
$this->em->flush();
Nothing deletes, neither it throws an exception to tell me it hasn't.
I doctrine flushed it too, checked the db, and it's still there..
UPDATE:
Straight after I removeElement, I looped through the user id = 23 dataset, and the comment data for id375 is not there... so it removed it from the collection but not from the DB, and I thought $em->flush() is supposed to do this?
Please advise
Thanks
You need to use
$em->remove($commentToDelete);
$em->flush();
Because the mapping is held in the comment you need to remove this entity to remove the reference before you flush which will save the state to the db.