Doctrine : One to one to one relation? - php

I'm making entities for a Symfony2 project at work.
I'm trying to make a system that controls the access to certain resources in function of an organisation (a company) and of a role. To sum it up, roles are the same for all the companies, but a company may make a resource available for a role, as another may not want to.
As for resources, they represent some actions and contents, such as the creation of this, the edition of that, and so on...
I attempted to solve this problematic with the following entity. It represents a one to one to one relationship between my three entities Organisation, Role and Resource.
I wanted to know if that kind of relation was possible/good, or if there is another way to manage resources.
/**
* #ORM\Entity
*/
class Organisation_Role_Resource
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Organisation")
*/
private $organisation;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Role")
*/
private $role;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="Aurae\UserBundle\Entity\Resource")
*/
private $resource;
Do you have any piece of advice on how to solve this problem?
Is there another/better way to represent resources (which are, in fact, pages and links) and to manage their access?

While this might be quite valid approach you would be really reinventing the wheel.
Symfony2 has it all implemented already as 'Access Control Lists' or (ACL):
http://symfony.com/doc/current/cookbook/security/acl.html
Check it out.... I think it covers everything you need...

Related

Doctrine 2 - Relate from abstract class to abstract class

Alright. This question is kind of hard to describe. But here goes. I'll post some images first, just incase someone gets what I'm doing from this image;
A Block is an element that can be used to fill a webpage or blogpost. This can be images, text or forms. These Blocks are ContentBlocks. Block has a DiscriminatorColumn and DiscriminatorMap properties that are used to join the right Block table and create the underlying Block element. (i.e. an ImageContentBlock)
On the other hand we have Forms. Forms consist of FormBlocks. These are certain common Form elements. (TextField, PhoneField etc).
I want to be able to relate to the Content- or FormBlocks from either Page, Post or Form.
How can I achieve this in Doctrine?
I could add an entityType and entityId field to the Block class. But that would remove the object orientated style of programming. I would rather refer to the owning ContentEntity. But then again. I need to join or relate to the Blocks.
Not every ContentEntity has Blocks. So I cannot add this as an property of ContentEntity.
Now. I could off course use a ManyToMany relationship and go with a JoinTable. I guess that would always work. But I would have to join twice.
I think your problem isn't primarily about the data relations but about the fact that you want to avoid duplicate code. This results in your “Entity” being at the top of your hierarchy, only because it has a few common properties that each entity should have. (By the way, naming an entity “Entity” is a bit confusing.)
Maybe what you're looking for are Traits. So, instead of providing id and active through an entity, it could as well be a trait:
trait CmsEntity
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="boolean")
*/
protected $active;
// add getters/setters and other code as you like
}
Now you can attach this trait to all the entities which should have the given properties.
/**
* #ORM\Entity
*/
class Page
{
use CmsEntity; // import the trait
/**
* #ORM\Column(type="text")
*/
private $header;
// etc.
}
This will make you free from the requirement of deriving all your entities from one master “Entity” which just carries some common properties.
And now you can create a direct relation between between “ContentEntity” and “Block” (1:n I'd guess), which is more logical.
There's also a nice article elaborating on using Doctrine with traits for further reading.

What is a framework? And what is Doctrine 2? [duplicate]

This question already has answers here:
What is a Web Framework? How does it compare with LAMP?
(3 answers)
Closed 8 years ago.
I know some HTML, PHP, CSS and MySQL. Something that I haven't got to grasps with yet is frameworks. I am trying my best to read what they are and what they do, but for the life of me I cannot understand it.
Please could somebody explain frameworks and Doctrine 2 in a very simple way, as I don't know where to start with them, but notice that they are certainly required.
I could tell you here what a framework is, but the answers to the question What is a software framework? already do it.
So, about Doctrine. It's an object relational mapper (ORM). It basically allows you to insert/update/select/delete an object in a relational database, or generate/update tables via classes.
Let's assume a simple Member table:
Usually, you would write a query to, for example, insert something in a table. Such as:
INSERT Member VALUES ('Andy', 'andy#example.com', 30);
What an ORM allows you to do, is to insert a mapped object into the table. The values in the table will be seen just as you would normally see them by inserting them via query.
Let's look at a very simple example of Doctrine in the Symfony framework:
namespace ExampleProject\MemberBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Member
* #ORM\Table()
* #ORM\Entity
*/
class Member {
/**
* #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="email", type="string", length=255)
*/
private $email;
/**
* #var string
* #ORM\Column(name="age", type="integer", length=3)
*/
private $age;
/* getters and setters here */
}
The above class is mapped (annotated with DocBlocks) and represents our Member table, describing which parts will be seen as columns in the database. Simply said: the mapped variables inside the class will be visible as columns in the database. And you also can tell by mapping these variables, which datatype you want the columns to have (string/integer etc).
Now in my code, I'm able to call the Doctrine entity manager, create a new Member object, initiate the properties and save it into the database, in a nice object-oriented syntax:
$em = $this->getDoctrine()->getEntityManager();
$member = new Member;
$member->setId($id);
$member->setName($name);
$member->setEmail($email);
$member->setAge($age);
$em->persist($member);
$em->flush();
As you can see, all we need to do is call to save the object in the database. In the background, the ORM also performs a INSERT query (similarly to the one I mentioned above). You even could enable a setting to see the actual query executed.
Now this may look quite unnecessary and lots of work. But it will save you a lot of time. It is more object oriented from your source code point of view, and you will be able to maintain your (medium/large) application much better than without using an ORM. Furthermore, if you currently have MySQL as a database, but you would like to change it to e.g., PostgreSQL, you can do so with minimal changes to your code as your ORM will take care of the underlying queries.
So in essence, the ORM is a database abstraction layer with object-oriented syntax.

Doctrine possible to reverse engineer inverse associations?

I have database with about 100 tables and I'm using Doctrine 2 as my Data Mapper. I successfully generated entities for my tables, however, I noticed that many-to-one relationships didn't generate bidirectionally. Only many-to-one part of the relation generates, the one-to-many does not.
For instance in my Company entity I have
/**
* #var \User
*
* #ManyToOne(targetEntity="User")
* #JoinColumns({
* #JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $user;
but I don't have anything pointing to the Company entity in User.
I am aware that Doctrine doesn't do this OOTB it says so in their documentation but I was wondering if there is a way to get around this limitation.
Writing 300+ relations by hand is a task I don't want to undertake.
Is there perhaps an alternative Data Mapper library for PHP that can solve this for me?
Thanks in advance.
I ended up using Propel because it generated everything wonderfully, albeit I ended up with some very large files (14k LoC).
It seems there simply isn't a PHP ORM that does everything right.

How to setup Symfony2 Bundles independently with related Entities

I am trying to figure out a smart way to implement my bundles with following requirements:
I have a Bundle with logic named LogicABundle
I have a Bundle with common things as design and Menus called
AppBundle
I have another Bundle with logic LogicBBundle with some entities
related to LogicABundle entities
I know want to be able to "deploy" two applications from this setup:
Application one uses the LogicABundle and AppBundle
The second one uses LogicABundle, LogicBBundle and AppBundle
The issue is, that for the second application I need to relate some Entities from LogicABundle to LogicBBundle, which causes the first "deploy" option to brake, if I just have an entity in LogicABundle pointing to LogicBBundle.
Is there a smart solution to deploy these two different applications independently?
Here is an example in order to make it easier to understand:
namespace My\LogicABundle\Entity\Game;
use Doctrine\ORM\Mapping as ORM;
/**
* My\LogicABundle\Entity\Game
*
* #ORM\Entity
*
*/
class Game
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $title
*
* #ORM\Column(name="title", type="string")
*/
private $title;
/**
*
* #var Message
* #ORM\ManyToOne(targetEntity="\My\LogicBBundle\Entity\Message", inversedBy="games")
* #ORM\JoinColumn(name="messag_id", referencedColumnName="id", nullable=false)
* #Assert\NotNull()
*/
private $message;
}
I want to be able to use the Game class in my standalone application only with LogicABundle, and in my second application I need the game Entity with message relation.
I am not sure, but I have the same problem and I just found that : http://symfony.com/en/doc/current/cookbook/doctrine/resolve_target_entity.html
Hope not to late ;)
If you are using Git (or SVN or another source countrol tool) I would recommend to create two separate Symfony2 applications (each in its on repository). Also, every bundle gets its own repository and I would use Composer to set up the dependencies correctly and then install the bundles (LogicABundle, LogicBBundle, AppBundle) as vendors.
Update: Since the different bundles need different entities, one way is to specify the base entity in the bundle that does only need the base entity and extend the entity in the other bundle with additional relations (see Doctrine Inheritance Mapping).
For example, define EntityA in LogicABundle and define EntityA2 in LogicBBundle where EntityA2 extends EntityA and adds additional relations to the entity.
Update: Since you do not have provided additional information why you need to do this, I can only guess now, but one additional idea would be to simply use the same entities in both bundles. The logic in LogicABundle would simply ignore the additional relations. I think that is what most developers would do in your situation.
Consider, for example, bundles that provide common functionality like FOSUserBundle. The bundle defines some models, but not every application that uses FOSUserBundle has to use every field of the entities (in a application I am currently developing I completely ignore the groups functionality of FOSUserBundle).
Please provider further information if it is possible to use a common entity class and ignore these additional relations.

Getting associated entries in Doctrine 2

I've decided that it would be a good asset to get familiar with an ORM and went for Doctrine 2 as the ORM of choice.
I'm working on a test project to learn the basics of Doctrine. Although most people usually go with a blog, I've decided to make a basic app in which you can save and track orders. My database schema would be as follows:
User
id
name
Product
id
name
price
Sales_order
id
user_id
product_id
quantity
unit_price
Hence, my Order model looks like:
/**
* #Entity
* #Table(name="sales_order")
*/
class Order {
/**
* #Id
* #Column(type="integer", nullable=false)
* #GeneratedValue(strategy="AUTO")
*/
private $Id;
/**
* #OneToOne(targetEntity="User", inversedBy="user")
*/
private $user;
/**
* #OneToOne(targetEntity="Product", inversedBy="product")
*/
private $product;
/**
* #Column(type="integer", nullable=false)
*/
private $quantity;
}
Now, the question is, is there a simple way of accessing all the orders from the user model? Should I write DQL (doctrine query language) for these kind of basic stuff or is there a way to easily get associated entities? I mean, there wouldn't be any point to this otherwise, right? Also, am I doing these associations correctly? I'm really confused in this very basic model... Detailed help is really appreciated. Thank you.
Firstly, don't worry too much about the database design. You should design your entities and use the SchemaTool.
Now, the question is, is there a simple way of accessing all the orders from the user model?
Do you mean access all of the orders from the user model, or access all the orders associated to a user?
If you meant the former, well you are doing things wrong (see below). If you meant the later, you should setup a bi-directional relationship between orders and users. (BTW, it would be OneToMany not OneToOne as one user would likely have many orders).
I'm really confused in this very basic model...
I think what you having trouble with - along with many PHP programmers - is the fundamental understandings of the DataMapper pattern and ultimately Domain Driven Design as well. Remember, you are dealing with persistable objects, not database tables.
I cannot provide detailed information here because I'd be writing a book, hence this I would recommend you get a book on Domain Driven Design to help kick start with the principles. There are a few good online resources available, like a series of blog posts by Federico Cargnelutti, however they aren't specific to Doctrine 2.

Categories