How to store system settings in entity - php

I'm currently doing system, which settings should be editable by admin. He cannot add them, but only choose/edit from existing one.
All the backend is done in Sonata.
Settings class:
class SystemSettings
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="key", type="string", nullable=true)
*/
private $key;
/**
* #ORM\Column(name="value", type="string", nullable=true)
*/
private $value;
}
Problem is that I have different value types to store. I have some booleans, lists, integers, etc. For example I want to display array of languages as a list, but when it comes to "posts on page" setting, user should be able to write down any integer he wants. Is there any proper way to store it and display?

The problem with using this method of storage is as you said, variable data types. Soon you will want nested configuration, and eventually you will be writing over complex queries to select and update embedded JSON strings (trust me, i know).
I can't give you an exact solution because it is a problem I am still trying to solve. However some solutions I have yet to explore include:
Using MongoDB. Because it stores data in JSON natively, it is fair more suited to storing arbitrary datatypes (within the range of scalar and arrays at least).
Or dynamic file configuration. Which is a writable file using XML, or JSON as a format to store arbitary data. A problem you might run into though is if the server software is run on multiple machines. However if you can implement the first solution, then this one is essentially the same.
In all cases, the configuration should be incorruptible in so far as if something is wrong, there should be static defaults for it to fall back on. I am looking into adapting the Symfony\Component\Config component to achieve this.

Related

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.

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.

Doctrine 2: Load entity and childs count

I have these two entities:
Message entity
class Message
{
/**
* #ManyToOne(targetEntity="User")
* #JoinColumn(name="author", referencedColumnName="id_user")
*/
protected $author;
User entity
class User
{
/**
* #Id
* #Column(type="integer", nullable=false, name="id_user")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Column(type="string", nullable=false)
*/
protected $name;
I need to get the total of messages of user and its data in order to echo something like this:
echo $user->getName() . " have {$user->totalOfMessage()}";
I now that I can make a relation in User entity to get a message collection. But I don't know if it necessary only to get the size.
Well, I found the answer. At least one good option.
As of Doctrine 2.1 you can mark associations as extra lazy. This means that calling $user->getMessages()->count() won't load the messages, it will just issue a COUNT query to the database.
You can read about extra lazy collections here: https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/tutorials/extra-lazy-associations.html
I've recently been trying to get the EXTRA_LAZY loading working and found what I think is quite a major mistake in the documentation as shown on page:-
http://www.doctrine-project.org/docs/orm/2.1/en/tutorials/extra-lazy-associations.html
I expect that most Doctrine users may realise that the fetch="EXTRA_LAZY" needs to be put on the 'owning' side of the ManyToMany relationship but the example shows the annotation being added to a line which contains 'mappedBy' which is NOT the owning side?
By adding the fetch="EXTRA_LAZY" directive to the non-owning side it gets completely ignored as I now know it should be. I think this should be more clearly stated in the documentation.
I could not find any article anywhere explaining this after exhaustive searching so I'd say this is probably worth an amendment to the docs?
In our use case it's made a particularly intensive block of processing which used quite a number of 'contains' calls and which constantly crashed due to exceeding memory limits into a quick process which now executes orders of magnitude faster.
Hope this info helps someone out there...

Doctrine : One to one to one relation?

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...

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