NOT NULL if value is true in another column - symfony

I'm creating my entities and I want to create an entity with two columns that need to have a specific constraint. If addressId is defined, then extAddressId can be null (and it has to be null).
/**
* #ORM\Entity()
* #ORM\Table(name="widgets")
*/
class Widget
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="integer")
*/
private $addressId;
/**
* #ORM\Column(type="integer")
*/
private $extAddressId;
}
I know how to do it with SQL but not with doctrine.
CREATE TABLE widgets
(
id integer,
addressId integer,
extAddressId integer,
CONSTRAINT if_addressId_then_extAddressId_is_not_null
CHECK ( (NOT addressId) OR (extAddressId IS NOT NULL) )
);

According to the documentation you can add check constraints like this :
/**
* #ORM\Column(type="integer", options={"check":"[your check condition]"})
*/
private $addressId;
/**
* #ORM\Column(type="integer", options={"check":"[your check condition]"})
*/
private $extAddressId;
Haven't tested myself.

Related

Validate embed form if not empty

I have two entities: Program and Widget
Program
class Program
{
....
/**
* #Assert\Valid
*
* #ORM\OneToOne(targetEntity="Widget", inversedBy="program", cascade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinColumn(nullable=true)
*/
private $widget;
}
Widget
class Widget
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="integer")
*/
private $addressId;
/**
* #ORM\Column(type="integer")
*/
private $extAddressId;
/**
* #ORM\Column(type="string")
*/
private $language;
/**
* #ORM\OneToOne(targetEntity="Program", mappedBy="widget")
*/
private $program;
}
I have two issues.
First I need to add a conditional constraint on Widget, addressId or extAddressId have te be defined, not both.
Second widget is not required for Program. It's either you let all form fields blank, like you don't want to add a widget to the form OR you fill the form but you have to respect the conditional constraint and of course the required fields.
I was trying to add a Callback as it's explained in the official doc here but I have no idea how to combine both.
First you have to define Assert von widget relation, like
Column Widet
#Assert\Valid()
As next, you have to work with expressions on the widget itself, like
Column adressId
#Assert\Expression(
* expression=" (this.getAdressId() and !this.extAdressId()) or !this.getAdressId() ",
* message="error.cant_be_enabled_with_adress_id"
* )
Column extAdressId
#Assert\Expression(
* expression=" (this.getExtAddressId() and !this.getAdressId()) or !this.getExtAdressId() ",
* message="error.cant_be_enabled_with_adress_id"
* )

doctrine composite key and one to many

I use Symfony 2.8. I have two table and in both the primary key is composed by 3 columns:
id, tipo_corso, comune
02, it, devi
01, en, capi
09, es, file
Obviously the two table have other different columns. I can't change the primary key by use only one or two columns. For one record in StranieriCRS table there are many record in EsoneroLingua table (OneToMany):
First entity:
class StranieriCRS
{
/**
* #ORM\Column(type="string")
* #ORM\Id
*/
private $id;
/**
* #ORM\Column(type="string")
* #ORM\Id
*/
private $tipo_corso;
/**
* #ORM\Column(type="string")
* #ORM\Id
*/
private $comune;
public function __construct($id, $tipo_corso, $comune)
{
$this->id = $id;
$this->tipo_corso = $tipo_corso;
$this->comune = $comune;
$this->esonerolingua = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #ORM\OneToMany(targetEntity="EsoneroLingua", mappedBy="stranieriCRS", fetch="EAGER")
*/
private $esonerolingua;
/**
* Get esonerolingua
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getEsonerolingua()
{
return $this->esonerolingua;
}
Second entity:
class EsoneroLingua
{
/**
* #ORM\Column(type="string")
* #ORM\Id
*/
private $id;
/**
* #ORM\Column(type="string")
* #ORM\Id
*/
private $tipo_corso;
/**
* #ORM\Column(type="string")
* #ORM\Id
*/
private $comune;
public function __construct($id, $tipo_corso, $comune)
{
$this->id = $id;
$this->tipo_corso = $tipo_corso;
$this->comune = $comune;
}
/**
* #ORM\ManyToOne(targetEntity="StranieriCRS", inversedBy="esonerolingua")
* #ORM\JoinColumns(
* #ORM\JoinColumn(name="id", referencedColumnName="id"),
* #ORM\JoinColumn(name="tipo_corso", referencedColumnName="tipo_corso"),
* #ORM\JoinColumn(name="comune", referencedColumnName="comune"),
* )
*/
private $stranieriCRS;
The problem occur when I want get the StranieriCRS object because he give me as result only one result...seems like a OneToOne relation.
My Controller:
$sql = $entityManager->createQuery("
SELECT c
FROM AppBundle:EsoneroLingua c
WHERE c.id = '1546871' and c.tipo_corso = 'C' and c.comune = '7868'
");
$test = $sql->getResult();
In $test I was expect N record of EsoneroLingua with the same record StranieriCRS but I get only one EsoneroLingua with the correct StranieriCRS object. Seems work like OneToOne relation...why? Plus if I made dump($sql->getSql()); I obtain the raw sql...I try to use it directly in my db and he give me the right result. Is it a Doctrine bug?
To make a bidirectionnal One-To-Many, specify the JoinColumns only in the Many-To-One side.
So, in StranieriCRS, remove the following lines :
* #ORM\JoinColumns(
* #ORM\JoinColumn(name="id", referencedColumnName="id"),
* #ORM\JoinColumn(name="tipo_corso", referencedColumnName="tipo_corso"),
* #ORM\JoinColumn(name="comune", referencedColumnName="comune"),
* )
And just let Doctrine guess the columns with the inversedBy and mappedBy attributes.
For more information on the mappings, see this page.

Doctrine2 How to check if there is the related record in

I have a bidirectional many-to-many between theese two entities:
Position
/**
* Position
*
* #ORM\Table(name="applypie_position")
* #ORM\Entity(repositoryClass="Applypie\Bundle\PositionBundle\Entity\PositionRepository")
*/
class Position
{
const IS_ACTIVE = true;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="Applypie\Bundle\UserBundle\Entity\Applicant", mappedBy="bookmarks")
*/
private $bookmarkedApplicants;
Applicant
/**
* Applicant
*
* #ORM\Table(name="applypie_applicant")
* #ORM\Entity
*/
class Applicant
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToMany(targetEntity="Applypie\Bundle\PositionBundle\Entity\Position", inversedBy="bookmarkedApplicants")
* #ORM\JoinTable(name="applypie_user_job_bookmarks",
* joinColumns={#ORM\JoinColumn(name="applicant_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="position_id", referencedColumnName="id")}
* )
*/
private $bookmarks;
My Problem is: In an PositionControllers Action which easily shows an position by ID i need to know if there the current Applicant whichs wants to see the position has an bookmark for the current position.
I first thought of get all the Bookmarks with $applicant->getBookmarks() and run in within a forearch, checking all the applicants bookmarks against the current position, but i think there must be an easier way?
thank you
If you want to stay object oriented you can do it this way:
class Applicant
{
// fields and ORM annotations
public function hasBookmark(Bookmark $bookmark) {
return $this->bookmarks->contains($bookmark);
}
class MyController
{
public function testAction() {
$applicant = $this->getUser(); // or however you fetch the applicant object
$bookmark = $bookmarkRepository->find($bookmarkId); // again, however you get the bookmark object
// #var boolean $applicantHasBookmark
$applicantHasBookmark = $applicant->hasBookmark($bookmark);
// other controller code
}

How do I generate ID when I have composite keys in Doctrine?

I have a Entity with composite keys. See below:
class BankAccount {
/**
* #ORM\Id
* #ORM\Column(type="integer")
*
*/
protected $bank;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="CompanyBundle\Entity\Company")
*/
protected $company;
...
}
because Doctrine has some issues with composite keys it won't generates sequences (I'm working in PostgreSQL), how do I deal with this in order to generate $bank which is the PK?
If sounds like you don't want a composite key, just a primary key on $bank and a foreign key on $company. If that's the case,
class BankAccount {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $bank;
/**
* #ORM\ManyToOne(targetEntity="CompanyBundle\Entity\Company")
*/
protected $company;
...
}
should do it.

Symfony2 Doctrine2 column being set to null

I have a system that took form information detailing a project, added it to a project table and is meant to add an entry into an assigned projects table to associate user with project (point of this is allowing multiple users for each project). Anyway I got this working without foreign keys, struggled to add them but eventually got them.
Unfortunately this additional has caused this error 'SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'projectId' cannot be null' whenever something is added to the assignedProjects table.
So my question is, have I missed something in my codes?
The code to add a new row to assignedProjects:
$assignedProject = new AssignedProjects();
$assignedProject->setProjectId($project->getId());
$assignedProject->setUserId($user[0]['id']);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($assignedProject);
$em->flush();
The code for the assignProjects entity:
class AssignedProjects
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer $projectId
*
* #ORM\Column(name="projectId", type="integer")
*/
private $projectId;
/**
* #ORM\ManyToOne(targetEntity="Projects", inversedBy="assignment")
* #ORM\JoinColumn(name="projectId", referencedColumnName="id")
*/
private $project;
/**
* #var integer $UserId
*
* #ORM\Column(name="userId", type="integer")
*/
private $userId;
/**
* #ORM\ManyToOne(targetEntity="Dev\UserBundle\Entity\User", inversedBy="assignment")
* #ORM\JoinColumn(name="userId", referencedColumnName="id")
*/
private $user;
(followed by the usual getters and setters)
and the project tables entity is:
class Projects
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $projectName
*
* #ORM\Column(name="projectName", type="string", length=255)
*/
private $projectName;
/**
* #ORM\OneToMany(targetEntity="AssignedProjects", mappedBy="project")
*/
protected $assignment;
Any help would be much appreciated!
Either you use the ProjectId and UserId columns and manage the relationship manually (not recommended) or you use the doctrine relationships(recommended), but don´t do both things. If you go for the second option, don´t include the projectId and userId columns, they are automatically created for you by doctrine. So, your AssignedProjects class should be:
class AssignedProjects {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id * #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Projects", inversedBy="assignment")
* #ORM\JoinColumn(name="projectId", referencedColumnName="id")
*/
private $project;
/**
* #ORM\ManyToOne(targetEntity="Dev\UserBundle\Entity\User", inversedBy="assignment")
* #ORM\JoinColumn(name="userId", referencedColumnName="id")
*/
private $user;
and in your controller you would do:
$assignedProject = new AssignedProjects();
$assignedProject->setProject($project);
$assignedProject->setUser($user[0]);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($assignedProject);
$em->flush();
Note that I am setting the Project and User fields, not the ids
By the way, unless you need to save extra data about this project assignement (things like the date or similar), you can declare a direct ManyToMany relationship between User and Project and do away with this class, Doctrine would generate the needed table by itself
With Doctrine2, you don't have to declare the foreign key (projectId) but only the association (project). So you can delete $projectId property, as well as setProjectId ans getProjectId methods. Same fix for $user...
Instead, you will use setProject like that :
$assignedProject = new AssignedProjects();
$assignedProject->setProject($project);
$assignedProject->setUser($user[0]);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($assignedProject);
$em->flush();
Have a look to Doctrine2 documentation, it will help you, for sure !
http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/association-mapping.html

Resources