i want to create a forms with only getter methods in the entity... Since I am working on already existing database which does not require to store or manipulate the data.
Hence I have created Entities for the products with only Getter methods and no Setter method.
However when i create form( like search query with some dropdowns etc) it always looking for set or Add methods. Is there a possibility if i can only use getters to get the data from the database.
And I do not want data to be modified at anytime in the future.
i tried with "read_only" but it still gives an error about setter and addMethod()
http://symfony.com/doc/current/reference/forms/types/form.html#read-only
EDIT:
I want to create a drop down ProductGroupcategory-> productSubcategory -> Product
like this(advance search): http://www.buycarspares.co.uk/
Complete Code:
https://gist.github.com/anonymous/8b2e576e69b1588e4f21
Relationships require add- and get-methods simply because it is about an array or arrayCollection of an object and not about the getters or setters for normal entity properties like strings.
Yes you can though some people might consider the solution to be worse than the problem. You could of course just declare your entity properties to be public. That would avoid not only setters but getters as well. Doctrine 2's lazy loading functionality would not work.
A more advanced approach it to realize that the form component uses a property access object to transfer data to and from your entity. That is where the 'add' and 'set' messages are coming from. Property access objects are also what allows you to use arrays as well as entities. http://symfony.com/doc/current/components/property_access/introduction.html
The form component allows you to plug in your own property access object which means that you can create your own access object which can write directly to private/protected variables using Reflection. This, by the way, is the same technique that Doctrine 2 uses to hydrate your entities using database information.
Of course I can already hear howls of protest of this approach mostly about violating encapsulation. But think about it for a moment before down voting. The form component really is just persisting and retrieving the state of an entity to and from an html document. Exactly what Doctrine 2 does. As long as you don't misuse the technique then there is no violation.
I routinely use this approach to avoid writing endless getters and setters. Seems to work fine in practice.
Related
I know this is kind of a question of faith and has been asked many times before, but the answers I've found were either too general, didn't apply to my use case, or didn't satisfy otherwise.
I'm currently building an application that uses classes as representation for database tables. These classes don't offer any methods of their own, I've written a parser class for each one that works with their objects and returns the data in the format I need, which makes the parent classes nothing more than data storages and makes a nice distinction between data and logic.
Now, the consensus in OOP seems to be that you always have to use getters and setters instead of accessing class attributes directly.
An argument I've often heard is that using getters and setters gives the possibility of extending those functions later on, but in my opinion this goes against YAGNI and some other concepts I can't remember the name of right now - that a method should do exactly what you would expect from its name. If I wanted to do something more than simply set a value, I would write a new method, not put that into my setter method, since that one is, per definition, only supposed to set attributes. So I might as well skip the setter and just access the attribute directly.
Another one is that you can put validation in your setters, which I already do in my API that accesses these classes. In my opinion you shouldn't just pass values and have the object tell you if your value is okay or not, but instead validate those values first before you pass them to the object.
I do understand the purpose of private/protected attributes in "usual" classes, but when the class is literally just a data container without any methods, is this really needed? In other words: is there a glaring disadvantage to using public values, when the setter methods for those (were they private) would all just look like public function getAttr($attr) { $this->atrr = $attr; } anyway?
You only need a data structure, but the only suitable PHP construct is the class.
Typically, in object-oriented analysis, design and programming, a class is a model of a thing or concept and it encapsulates any knowledge and/or behaviour of the thing or concept.
However, in the context of this question, encapsulation is not needed since you only require a data structure.
I've got an entity with a lot of linked properties, when I'm handling a CSV import, I don't want to create $em->getReference() calls for all the linked fields (mainly because i want to keep it as abstract as possible and don't want to hard code all the possible references).
I rather want to do this in the Entity setter method for the given properties. However that would require me to access doctrine from within the Model which in its turn is a bad practice.
Should i access the entity's Metadata and go from there or is there a better approach to this, which I haven't yet mentioned?
Doing it in the setter, really messes up the whole SOA thing. If you care about the code being decoupled and abstract you can use Dependency Inversion.
Let's say you have entity A that has associations to entity B and C, then for getting the references to correct B and C instances from the raw data you get from the CSV, you would define two interfaces e.g: BRepositoryInterface and CRepositoryInterface, they both might contain a single method find($id), but they still have to be distinct. Now make your Doctrine Repositories for the respective entities implement these interfaces and inject them into the service where create entity A.
If you really wanna make some good code, then you should create separate classes implementing each of these interfaces, and then inject your Doctrine Repositories into them, these classes then act as wrappers for those repositories, this way you have a distinct layer between your DataMapper layer and your business logic layer, which gives you the abstraction you want.
This is what I've learned in my recent studies on good code, DDD and Design patterns. It is no where near perfect(not that there is such a thing). Any Ideas/Comments would be appreciated.
Update: In regards to your comment:
One of the main things that good design strives for is "capturing the language of domain experts", (see this source item no.4 for a description of these legendary beings).i.e: What is your code in plain English?
What your code says is basically find the Objects with these given ids from the repositories of the Entities that have an association to A.This looks pretty good since you have no explicit dependencies on what A has associations to.But looking at it closer, you'll see that you do have dependencies on actual B and C Objects and their repositories, since when you provide an id for some Object, you're not just providing an id, but you're also implicitly stating what that object is, otherwise an id would have no meaning other than it's scalar Value.However that approach definitely has it's use cases both in Semantics of the Design, and RAD.But there is still the issue of Law of Demeter, but it can be solved, see below:
Either way I think you should definitely have a factory for A objects that looks something like this.
class AFactory{
protected $br;
protected $cr;
public function __construct(BRepositoryInterface $br, CrepositoryInterface $cr){
$this->br = $br;
$this->cr = $cr;
}
public function create($atr1, $atr2, $bId, $cId){
$b = $this->br->find($bId);
$c = $this->cr->find($cId);
return new A($atr1, $atr2, $bId, $cId);
}
}
Now you can actually create this factory using the design you stated by having another factory for this factory, this will also solve the issue with Law of Demeter.That Factory will have the Entity Manager as it's dependency, it will read A's metadata, and fetch the Repositories of the related objects based on that metadata, and create a new AFactory Instance from those repositories, now if you implement those interfaces (BRepositoryInterface and CRepositoryInterface) in your actual Doctrine Repositories, the AFactory instance will be successfully created.
Using Doctrine, is it possible to map to properties which don't actually exist using magic methods?
I'm doing the mapping with YAML.
For example, if I wanted to map to a property named "demo", but SomeClass::$demo didn't actually exist. I'd want to some combination of __get(), __set(), __isset() and __call() to handle $demo (and getDemo() and setDemo()) and do something else with them.
I've tried setting this up, but I'm getting an error:
Uncaught exception 'ReflectionException' with message 'Property My\Bundle\DemoBundle\Entity\SomeClass::$demo does not exist'
I'm not sure if there is something special with the ReflectionProperty that causes it to miss my magic methods, or if I'm maybe missing a magic function. However, as far as I can tell, ReflectionProperty should interact with them.
Any ideas?
UPDATE:
Upon further investigation, it looks like the ReflectionProperty constructor will throw an exception and won't trigger the magic methods.
Does anyone else know of means to map Doctrine to dynamic properties?
Thanks.
UPDATE 2:
To example what I'm trying to accomplish.
Basically, I have a generic User object which just contains the base properties needed to handle actually being a user (roles, password, salt, username, etc.). However, I want to be able to extend this object to add application-and-user-specific meta data.
So, say I create a Forum bundle. I could then I could dynamically hook up meta data related to the user for use with the Forum. I don't want to put it directly in the User bundle, because then the User bundle becomes less flexible.
If I could somehow dynamically inject new data in to the user, it could all be loaded in a single query with the user, instead of having to be loaded in a separate query. I know there are some other methods to do this, which I've already explored and even used to a limited extend. However, it'd be much nicer if I could dynamically create these associations, which really shouldn't be that difficult of a leap.
If you don't need to search on these dynamic properties then just add a property called data to your entity and map it to a doctrine array type. Now do your majic stuff and store the dynamic properties in the data array.
A second approach might be along these lines: http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html. For each installation you might be able to give the administrators of making a custom entity.
But as long as you don't need to directly query on your dynamic properties then the first method works well.
Intoduction problem:
What is the best practice to build my class T object, when I receive it from a MongoCursor::getNext()? As far as it goes, getNext() function of a MongoCursor returns with an array. I wish to use the result from that point as an object of type T.
Should I write my own constructor for type T, that accepts an array? Is there any generic solution to this, for example when type T extends G, and G does the job as a regular way, recursively (for nested documents).
I'm new to MongoDB, and I'd like to build my own generic mapper with a nice interface.
Bounty:
Which are the possible approaches, patterns and which would fit the concept of MongoDB the most from the view of PHP.
This answer has been rewritten.
Most data mappers work by representing one object per class or "model" is normally the coined term. If you wish to allow multiple accession through a single object (i.e. $model->find()) it is normally demmed so that the method will not actually return an instance of itself but instead that of an array or a MongoCursor eager loading classes into the space.
Such a paradigm is normally connected with "Active Record". This is the method that ORMs, ODMs and frameworks all use to communicate to databases in one way or another, not only for MongoDB but also for SQL and any other databases to happen to crop up (Cassandra, CouchDB etc etc).
It should be noted immediately that even though active record gives a lot of power it should not be blanketed across the entire application. There are times where using the driver directly would be more benefical. Most ORMs, ODMs and frameworks provide the ability to quickly and effortlessly access the driver directly for this reason.
There is, as many would say, no light weight data mapper. If you are going to map your returned data to classes then it will consume resources, end of. The benefit of doing this is the power you receive when manipulating your objects.
Active record is really good at being able to provide events and triggers from within PHP. A good example is that of an ORM I made for Yii: https://github.com/Sammaye/MongoYii it can provide hooks for:
afterConstruct
beforeFind
afterFind
beforeValidate
afterValidate
beforeSave
afterSave
It should be noted that when it comes to events like beforeSave and afterSave MongoDB does not possess triggers ( https://jira.mongodb.org/browse/SERVER-124 ) so it makes sense that the application should handle this. On top of the obvious reason for the application to handle this it also makes much better handling of the save functions by being able to call your native PHP functions to manipulate every document saved prior to touching the database.
Most data mappers work by using PHP own class CRUD to represent theirs too. For example to create a new record:
$d=new User();
$d->username='sammaye';
$d->save();
This is quite a good approach since you create a "new" ( https://github.com/Sammaye/MongoYii/blob/master/EMongoDocument.php#L46 shows how I prepare for a new record in MongoYii ) class to make a "new" record. It kind of fits quite nicely semantically.
Update functions are normally accessed through read functions, you cannot update a model you don't know the existane of. This brings us onto the next step of populating models.
To handle populating a model different ORMs, ODMs and frameworks commit to different methods. For example, my MongoYii extension uses a factory method called model in each class to bring back a new instance of itself so I can call th dynamic find and findOne and other such methods.
Some ORMs, ODMs and frameworks provide the read functions as direct static functions making them into factory methods themselves whereas some use the singleton pattern, however, I chose not to ( https://stackoverflow.com/a/4596323/383478 ).
Most, if not all, implement some form of the cursor. This is used to return multiples of the models and directly wraps (normally) the MongoCursor to replace the current() method with returning a pre-populate model.
For example calling:
User::model()->find();
Would return a EMongoCursor (in MongoYii) which would then sotre the fact that the class User was used to instantiate the cursor and when called like:
foreach(User::model() as $k=>$v){
var_dump($v);
}
Would call the current() method here: https://github.com/Sammaye/MongoYii/blob/master/EMongoCursor.php#L102 returning a new single instance of the model.
There are some ORMs, ODMs and frameworks which implement eager array loading. This means they will just load the whole result straight into your RAM as an array of models. I personally do not like this approach, it is wasteful and also does not bode well when you need to use active record for larger updates due to adding some new functionality in places that needs adding to old records.
One last topic before I move on is the schemaless nature of MongoDB. The problem with using PHP classes with MongoDB is that you want all the functionality of PHP but with the variable nature of MongoDB. This is easy to over come in SQL since it has a pre-defined schema, you just query for it and jobs done; however, MongoDB has no such thing.
This does make schema handling in MongoDB quite hazardous. Most ORMs, ODMs and frameworks demand that you pre-define the schema in the spot (i.e. Doctrine 2) using private variables with get and set methods. In MongoYii, to make my life easy and elegant, I decided to retain MongoDBs schemaless nature by using magics that would detect ( https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L26 is my __get and https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L47 is my __set ), if the property wa inaccessible in the class, if the field was in a internal _attributes array and if not then just return null. Likewise, for setting an attribute I would just set in the intrernal _attributes variable.
As for dealing with how to assign this schema I left internal assignment upto the user however, to deal with setting properties from forms etc I used the validation rules ( https://github.com/Sammaye/MongoYii/blob/master/EMongoModel.php#L236 ) calling a function called getSafeAttributeNames() which would return a list of attributes which had validation rules against them. If they did not have validation rules then those attributes which existed in the incoming $_POST or $_GET array would not be set. So this provided the ability for a schema, yet secure, model structure.
So we have covered how to actually use the root document you also ask how to data mappers handle subdocuments. Doctrine 2 and many others provide full class based subdocuments ( http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/reference/embedded-mapping.html ) but this can be extremely resourceful. Instead I decided that I would provide helper functions which would allow for flexible usage of subdocument without eager loading them into models and so consuming RAM. Basically what I did was to leave them as they are a provide a validator ( https://github.com/Sammaye/MongoYii/blob/master/validators/ESubdocumentValidator.php ) for validating inside of them. Of course the validator is self spawning so if you had a rule in the validator that used the validator again to issue a validation of a nested subdocument then it would work.
So I think that completes a very basic discussion of ORMs, ODMs and frameworks use data mappers. Of course I could probably write an entire essay on this but this is a good enough discussion for the minute I believe.
I'm just wondering if someone can help me understand how to make the best use of objects in PHP.
My understanding of a PHP object is that is should represent an entity, providing methods to get and alter the properties of that entity. For example an object entitled Post would hold all the properties of a single post, which could be accessed and modified as appropriate.
What causes me some confusion is that libraries like CodeIgniter don't use objects in this manor. They treat classes more like wrappers for a group of functions. So a 'Posts' class in CodeIgniter would not hold properties of one post, it would provide functions for fetching, editing and deleting posts.
So what happens if I want to get every post out of a database and put it into a Post object? My understanding of it is I would in fact need two classes 'Posts' and 'Post', one that defines the Post object and one that handles fetching the Posts from the database and putting them into Post objects.
Do these two types of class have a name ('Proper' objects / Collections of functions)? And is it common to have two classes working together like this or have I completely misunderstood how to use objects?
Instead of having a Post object would it make more sense to have a method in my Posts class called getSinglePost($id) that just returned an array?
Hopefully that question makes sense, looking forwards to getting some feedback.
For an introduction, see What is a class in PHP?
For the answer, I'll just address your questions in particular. Search for the terms in bold to learn more about their meaning.
My understanding of a PHP object is that is should represent an entity, providing methods to get and alter the properties of that entity.
Entities are just one possible use for objects. But there is also Value Objects, Service Objects, Data Access Objects, etc. - when you go the OO route, everything will be an object with a certain responsibility.
What causes me some confusion is that libraries like CodeIgniter don't use objects in this manor.
Yes, Code Igniter is not really embracing OOP. They are using much more of a class-based-programming approach, which is more like programming procedural with classes and few sprinkles of OOP.
They treat classes more like wrappers for a group of functions. So a 'Posts' class in CodeIgniter would not hold properties of one post, it would provide functions for fetching, editing and deleting posts.
That is fine though. A posts class could be Repository, e.g. an in-memory collection of Post Entities that has the added responsibility to retrieve and persist those in the background. I'd be cautious with Design Patterns and Code Igniter though since they are known to use their own interpretation of patterns (for instance their Active Record is more like a Query Object).
So what happens if I want to get every post out of a database and put it into a Post object?
Lots of options here. A common approach would be to use a Data Mapper, but you could also use PDO and fetch the data rows directly into Post objects, etc.
My understanding of it is I would in fact need two classes 'Posts' and 'Post', one that defines the Post object and one that handles fetching the Posts from the database and putting them into Post objects.
That would be the aforementioned Repository or Data Mapper approach. You usually combine these with a Table Data Gateway. However, an alternative could also be to not have a Posts class and use an Active Record pattern, which represents a row in the database as an object with business and persistence logic attached to it.
Do these two types of class have a name ('Proper' objects / Collections of functions)? And is it common to have two classes working together like this or have I completely misunderstood how to use objects?
Yes, they work together. OOP is all about objects collaborating.
Instead of having a Post object would it make more sense to have a method in my Posts class called getSinglePost($id) that just returned an array?
That would be a Table Data Gateway returning Record Sets. It's fine when you don't have lots of business logic and can spare the Domain Model, like in CRUD applications
Class should ideally has the same interpretation as anywhere else in PHP as well. Class starts with abstraction, refining away what you don't need. So it's entirely up to you to define the class the way you want it.
Codeigniter does have a strange way of initiating and accessing objects. Mainly because they are loaded once and used afterwards, prevents it from having functionality around data. There are ways around it and normal handling of classes still possible. I usually use a auto loader and use normal classes.
"So what happens if I want to get every post out of a database and put it into a Post object? My understanding of it is I would in fact need two classes 'Posts' and 'Post',"
You are essentially referring to a MODEL to access the data ("posts") and an Entity to represent the "post". So you would load the model once and use it to load up as many entities as you would like.
$this->load->model("posts");
$this->posts->get_all(); // <- This can then initiate set of objects of type "Post" and return. Or even standard classes straight out from DB.
Your understanding of an object is correct. A post is a single object of a class Post. But of course you need a function, that retrieves posts from a database or collects them from somewhere else. Therefore you have so called Factory classes. That's what can cause some confusion.
Factories can be singletons, which normally means that you have one instance of this class. But you don't need to instantiate a factory at all (and instead use static functions to access the functionality):
$posts = PostFactory::getPosts();
And then the function:
static function getPosts() {
$list = array();
$sql = "select ID from posts order by datetime desc"; // example, ID is the primary key
// run your sql query and iterate over the retrieved IDs as $id
{
...
$post = new Post($id);
array_push($list, $post);
}
return $list;
}
Inside this factory you have a collection of "access"-functions, which do not fit elsewhere, like object creation (databasewise) and object retrieval. For the second part (retrieval) it is only necessary to put the function into a factory, if there is no "parent" object (in terms of a relation). So you could have an entity of class Blog, you instantiate the blog and then retrieve the posts of the blog via the blog instance and don't need a separate factory.
The naming is only there to help you understand. I wouldn't recommend to call a class Post and it's factory Posts since they can easily be mixed up and the code is harder to read (you need to pay attention to details). I usually have the word "factory" mixed in the class name, so I know that it is actually a factory class and others see it too.
Furthermore you can also have Helper classes, which don't really relate to any specific entity class. So you could have a PostHelper singleton, which could hold functionality, which doesn't fit neither in the object class nor in the factory. Although I can't think of any useful function for a Post object. An example would be some software, which calculates stuff and you have a Helper, which performs the actual calculation using different types of objects.