How much should doctrine record do? - php

I'm creating my own CMS and use doctrine for database.
Now I wonder, when I crate Post record, how much work should that record do?
An example:
I have Post -> Categories relation (one to many), should I create separate functions to append categories (to look if Post already has category, etc. ) or should Post do that using accessors / mutators?
What's the best practice?

I think adding methods for the purprose you described is a good idea. Doctrine can sometimes be a bit tricky if you try to override the default actions that happen when accessing the properties.
In general, if there's anything that needs more than the default action, I would recommend having it as a method in the model class.
If you have a specific table with some table-specific actions, such as get every object by some rule, then it's a good idea to add a new method to the table-specific SomeTable class.
Since this is kind of like ActiveRecord, you would have the domain logic in the Doctrine record object.

Related

Using a single flexible model

A quick question this time about the M in Mvc.(using codeigniter, but the question is general)
Suppose I have several models that are responsible for accessing several tables in my database, Is it frowned upon making one flexible model that can deal with everything?
specifically in php-codeigniter, for example:
$this->MY_model->getByID($table,$ID)
So this example code can be used to get by ID of any table I want thus saving me time and I'm able to reuse most of my model code.
This of course can be expanded further
$this->MY_model->update($table,$info) as an example.
So my question is, If all of the above is okay, Where is the 'limit' to such operations? Naturally we wouldn't want something really specific in this type of model, like this method:
$this->MY_model->getAllActiveUsers()
My basic approach is this:
Any method that can be used in more than one table should be used in the extended model.
Any method that should be used in only one table, should be in it's own model.
Just to be clear i'm not looking for an opinion, But rather wondering what's the standard approach to these issues.(for example, imagine an application with 50 models, should CRUD be written for all 50 of them?)
Thanks in advance!
What you are mulling about is pretty standard operation for most Codeigniter developers. If you are going to be doing a lot of CRUD in the DB, then it makes sense to add a set of generic CRUD methods to your base MY_model and then extend it. If you do a search on Google...you'll likely get results for 100s of people who have setup their own base models including CRUD and other common methods used by most Codeigniter projects...here are just a couple:
https://github.com/jamierumbelow/codeigniter-base-model
https://github.com/jenssegers/CodeIgniter-My-Model
should CRUD be written for all 50 of them?
No. You would extend your base model and use it's generic CRUD methods where they make sense and just override certain properties (table name). Then, if you needed something more specific you could create additional, more granular methods in your new model as you suggested.

PHP Objects - Patterns and correct usage

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.

Best OOP approach for this simple PHP app?

Ok, I couldn't insert the overview image, but I'm required to create a PHP app for my studies, it must allow student to register, and the administrator to edit course and student info.
We are not required to code it in an OOP style, but since its the best programming practice to code in OOP, why not learn OOP from the beginning.
I'm a beginner but I know the basics about OOP, classes, inheritance, setters and getters and all that cool lingo, but I'm struggling to decide which parts of this app should be objects, should I make course and student classes or add, edit and delete classes? Any advice on how to approach and visualize such a problem would be appreciated.
Very roughly: This is how I would do it:
Store your data in SQL or XML. You will need two SQL tables, one for Students and one for Courses. You can use one XML file containing all the data, or you can use two files (which I recommend).
Create a class called, for example, dataItem with a property like '$arr_fields' corresponding to a single data record (a single row in a SQL table, or an XML record).
The dataItem class should have the following methods (all public):
loadFromSQL() (or loadFromXML())
saveToSQL() (or saveToXML())
add(), edit() and delete()
a view() method using HTML
These methods are obviously used to read and write data between the SQL/XML data and $arr_fields of the class, and to display the data in $arr_fields. The keys of $arr_fields are the SQL column names (or XML tag or attribute names) for the specific SQL table.
Try not to call loadFromSQL() or saveToSQL() in your constructor or in any of the other methods which are used to modify only the class data. Keep these actions separate. EDIT: This is a personal preference which helps me to keep track of the state of my objects.
Create Student and Course classes that extends the dataItem class.
You can override methods, for instance the view() method, inside your extended classes if you need to.
Then you can call the methods in Students and Courses from an Admin object (like rcdmk suggested) or maybe from StudentFolder and CourseFolder classes whose view() method contains buttons for the actions that need to be performed. (Let StudentFolder and CourseFolder extend a Folder class that you create).
UPDATE:
For example: If your primary key in a SQL table is id, then dataItem's loadFromSQL($id, $tablename) should set $arr_fields so that its keys are the column names and it's values are the values from the row whose primary value is equal to $id.
In Students, you can then override loadFromSQL() as follows:
class Students extends dataItem {
// other attributes
public function loadFromSQL($id) {
parent::loadFromSQL($id, "Students");
}
}
EDIT: On reconsideration, it might be better to set $arr_fields["id"] = $id and also set $tablename with the constructor for dataItem - then you never have to override loadFromSQL() or specify parameters for it. loadFromSQL() should then load the record if it exists. saveToSQL() should save $arr_fields in SQL if $arr_fields["id"] is set and create a new record if it is not set. Anyway, you must find a consistent way of interacting with the data which works for you, these are just possibilities.
However, if you are not experienced with OOP and SQL or XML, you might be opening a can of worms for yourself and it might be better to just do your assignment using functions only and php arrays for your data. Unless you have some time to learn...
From a simple perspective:
Abstract the main objects as classes and use methods for actions of this objects:
Student (object) are deleted (action) by the Admin (object), so
Admin class will have a deleteStudent method, because Admin deletes Students.
Another aprouch is to concentrate all Student related actions in the Student class:
Student class will have a public delete method that Admin can use.
Anyone that think this in better ways of explanation can edit this wiki.
Think about which aspects of your system are actually objects, you know, something you can do something with. The methods are what you do to the objects. So, you're on the right track with course and student classes, and add, edit, and delete would be methods of those classes.
But don't get too bogged down with it. If it's not your core assignment objective, you could quickly get in over your head by trying to do everything exactly the right way. If you can formulate a clear way to get to where you need to go, then go for it, if it seems confusing, back off it a little and learn some more.
You say that you know the basis of OOP, however you ask whether you should create Course, Student classes OR Add, Delete, Edit classes. Well maybe there are other practices, but I guess the most popular one and the only I am aware of is to use nouns as classes and verbs as their methods. Hence, intuitively there is something wrong with class "Add" or "Edit". What I would have done if I were were, is to think of all "entities" that might be considered an object - like Student, Course, Lecturer, Class (Room) and depending on how advanced your model should be you can add more like Building etc. Then try to implement basic things like creating new student, registering for a course, associating teacher with a course etc. Once you have it in place and IT IS WORKING you might want to add advanced things, like inheritance. For example you might want to say, that both Teacher and Student are a Person so you might want to create such abstract class and use inheritance.

What does a Data Mapper typically look like?

I have a table called Cat, and an PHP class called Cat. Now I want to make a CatDataMapper class, so that Cat extends CatDataMapper.
I want that Data Mapper class to provide basic functionality for doing ORM, and for creating, editing and deleting Cat.
For that purpose, maybe someone who knows this pattern very well could give me some helpful advice? I feel it would be a little bit too simple to just provide some functions like update(), delete(), save().
I realize a Data Mapper has this problem: First you create the instance of Cat, then initialize all the variables like name, furColor, eyeColor, purrSound, meowSound, attendants, etc.. and after everything is set up, you call the save() function which is inherited from CatDataMapper. This was simple ;)
But now, the real problem: You query the database for cats and get back a plain boring result set with lots of cats data.
PDO features some ORM capability to create Cat instances. Lets say I use that, or lets even say I have a mapDataset() function that takes an associative array. However, as soon as I got my Cat object from a data set, I have redundant data. At the same time, twenty users could pick up the same cat data from the database and edit the cat object, i.e. rename the cat, and save() it, while another user still things about setting another furColor. When all of them save their edits, everything is messed up.
Err... ok, to keep this question really short: What's good practice here?
From DataMapper in PoEA
The Data Mapper is a layer of software
that separates the in-memory objects
from the database. Its responsibility
is to transfer data between the two
and also to isolate them from each
other. With Data Mapper the in-memory
objects needn't know even that there's
a database present; they need no SQL
interface code, and certainly no
knowledge of the database schema. (The
database schema is always ignorant of
the objects that use it.) Since it's a
form of Mapper (473), Data Mapper
itself is even unknown to the domain
layer.
Thus, a Cat should not extend CatDataMapper because that would create an is-a relationship and tie the Cat to the Persistence layer. If you want to be able to handle persistence from your Cats in this way, look into ActiveRecord or any of the other Data Source Architectural Patterns.
You usually use a DataMapper when using a Domain Model. A simple DataMapper would just map a database table to an equivalent in-memory class on a field-to-field basis. However, when the need for a DataMapper arises, you usually won't have such simple relationships. Tables will not map 1:1 to your objects. Instead multiple tables could form into one Object Aggregate and viceversa. Consequently, implementing just CRUD methods, can easily become quite a challenge.
Apart from that, it is one of the more complicated patterns (covers 15 pages in PoEA), often used in combination with the Repository pattern among others. Look into the related questions column on the right side of this page for similar questions.
As for your question about multiple users editing the same Cat, that's a common problem called Concurrency. One solution to that would be locking the row, while someone edits it. But like everything, this can lead to other issues.
If you rely on ORM's like Doctrine or Propel, the basic principle is to create a static class that would get the actual data from the database, (for instance Propel would create CatPeer), and the results retrieved by the Peer class would then be "hydrated" into Cat objects.
The hydration process is the process of converting a "plain boring" MySQL result set into nice objects having getters and setters.
So for a retrieve you'd use something like CatPeer::doSelect(). Then for a new object you'd first instantiate it (or retrieve and instance from the DB):
$cat = new Cat();
The insertion would be as simple as doing: $cat->save(); That'd be equivalent to an insert (or an update if the object already exists in the db... The ORM should know how to do the difference between new and existing objects by using, for instance, the presence ort absence of a primary key).
Implementing a Data Mapper is very hard in PHP < 5.3, since you cannot read/write protected/private fields. You have a few choices when loading and saving the objects:
Use some kind of workaround, like serializing the object, modifying it's string representation, and bringing it back with unserialize
Make all the fields public
Keep them private/protected, and write mutators/accessors for each of them
The first method has the possibility of breaking with a new release, and is very crude hack, the second one is considered a (very) bad practice.
The third option is also considered bad practice, since you should not provide getters/setters for all of your fields, only the ones that need it. Your model gets "damaged" from a pure DDD (domain driven design) perspective, since it contains methods that are only needed because of the persistence mechanism.
It also means that now you have to describe another mapping for the fields -> setter methods, next to the fields -> table columns.
PHP 5.3 introduces the ability to access/change all types of fields, by using reflection:
http://hu2.php.net/manual/en/reflectionproperty.setaccessible.php
With this, you can achieve a true data mapper, because the need to provide mutators for all of the fields has ceased.
PDO features some ORM capability to
create Cat instances. Lets say I use
that, or lets even say I have a
mapDataset() function that takes an
associative array. However, as soon as
I got my Cat object from a data set, I
have redundant data. At the same time,
twenty users could pick up the same
cat data from the database and edit
the cat object, i.e. rename the cat,
and save() it, while another user
still things about setting another
furColor. When all of them save their
edits, everything is messed up.
In order to keep track of the state of data typically and IdentityMap and/or a UnitOfWork would be used keep track of all teh different operations on mapped entities... and the end of the request cycle al the operations would then be performed.
keep the answer short:
You have an instance of Cat. (Maybe it extends CatDbMapper, or Cat3rdpartycatstoreMapper)
You call:
$cats = $cat_model->getBlueEyedCats();
//then you get an array of Cat objects, in the $cats array
Don't know what do you use, you might take a look at some php framework to the better understanding.

What do you think of returning select object instead of statement result?

I would have liked to know if it was a good idea to return a select object from a method like '$selectObj = getSomethingByName($name)' to then pass it to another method like 'getResult($selectObj)' which will do the trick.
The idea is to be able to pass the select object to any usefull function like 'setLimit(10)' or addCriteria('blabla') depending on my model...
But is it a good idea to do this ? it could be 'unsecure' because user will be able to modify the object himself, and i should not want to this..
I used to do simple method before like above but returning the result as a row... but it's sometimes painfull when you have complex statement depending on different tables..
The problem you are facing (complex statements depending on different tables) is an old and widespread problem with ORM frameworks in general. There are lots of things SQL can do, that an ORM doesn't do very well. Inevitably, you have to make up the different in complexity by writing lots of complicated code in your Controller or your View.
Instead, use a Domain Model pattern and encapsulate the complex multi-table database logic into one place, so your Controllers and Views don't have to know about all the sundry details. They just know about the interface of your Domain Model class, and that class has the sole responsibility to know how to fetch the information from the database.
Remember: a Model "HAS-A" table (or multiple tables) -- instead of Model "IS-A" table.

Categories