I'm trying to find out what the best way would be to have a specification pattern in PHP where the specifications could (optionally) by transformed to PHP.
I am exploring some new directions and am testing how well they would work. Code and ideas are still very unclear in my mind.
Minimal interfaces would be like these:
interface IRepository {
public function get(ISpecification $specification);
}
interface ISpecification {
public function isSatisfiedBy($candidate);
}
If the repository hides a sql database the specification would need to transform to sql. Adding a ->toSQL() method seems ad hoc. A class that translates the specifications is also an option but it seems like a lot of overhead to finally generate the sql.
Ideas appreciated.
Quoting from POEAA (pg.324):
Under the covers, Repository combines Metadata Mapping (329) with a Query Object (316) to automatically generate SQL code from the criteria. Whether the criteria know how to add themselves to a query, the Query Object (316) knows how to incorporate criteria objects, or the Metadata Mapping (306) itself controls the interaction is an implementation detail.
The criteria in this descriptions are of course your Specification pattern. I'd say your suggested approach to use a toSQL method on the criteria objects is fine when the application is relatively small. Like you already said, going the other routes is more difficult, but it also provides greater flexibility and decoupling. In the end, only you can decide.
Related
I have stumbled upon PHP League Fractal which shows that the purpose is to ensure output format between storage and output (client).
I've been working with APIs for over a year, and I have constructed toArray() functions for most of my entities that I wish to return. With the aid of Eloquent, you can overload the toArray() function and decorate from there also if you have attached your entity model with Eloquent model.
Example:
public function toArray()
{
$array = parent::toArray();
$array['extra'] = true;
...
return $array;
}
If Apis should be fast and lightweight, what advantages does PHP League's Fractal have over implementing a toArray() or have a format($data) function from a repository/manager? Is it due to OOP? if so can someone show an example?
For me the advantages are:
consistent response format enforced by passing models through Fractal's resource objects
ability to rather easily change the response format throughout the application with a simple switch of a serialiser (e.g., from json-api to hal and possibly more). For json-api it does the boring stuff like splitting actual response data and root metadata. Also you can easily change response depending of Accept header, which might be harder with array (you'd need to restructure it and certainly you don't want that clutter in your controller).
automation of links generation e.g., for pagination
I think first two are not exclusive to Fractal, but would be a purpose of having any abstraction for response formatting.
What is unclear for me, is where does something like Fractal belong? I'm a big fan of the view that the model should be able to represent itself, like it does with __toString. But then again one might argue that it's more a concern of the presentation than the model. With using fractal's pagination, embedding support it get even less clear, because that (for me) strays a bit beyond the presentation itself.
Speed concern is of course valid, but you can optimise elsewhere, e.g. by caching whole response content on something like varnish or some laravel package that performs the similar role if you don't have the infrastructure (caveat being that it's not applicable to every use case, authorised or varied user-specific responses being case in point).
As for examples I can recommend two, beside the package docs:
http://www.sitepoint.com/fractal-practical-walkthrough/
http://laravelista.com/laravel-fractal/
Would love to see some writeup of how something like Fractal can fit into a bigger, structured project.
Separation of Concerns or Single Responsibility Principle
The majority of the questions in the dropdown list of questions that "may already have your answer" only explain "theory" and are not concrete examples that answer my simple question.
What I'm trying to accomplish
I have a class named GuestbookEntry that maps to the properties that are in the database table named "guestbook". Very simple!
Originally, I had a static method named getActiveEntries() that retrieved an array of all GuestbookEntry objects that had entries in the database. Then while learning how to properly design php classes, I learned two things:
Static methods are not desirable.
Separation of Concerns
My question:
Dealing with Separation of Concerns, if the GuestbookEntry class should only be responsible for managing single guestbook entries then where should this getActiveEntries() method go? I want to learn the absolute proper way to do this.
I guess there are actually two items in the question:
As #duskwuff points out, there is nothing wrong with static methods per-se; if you know their caveats (e.g. "Late Static Binding") and limitations, they are just another tool to work with. However, the way you model the interaction with the DB does have an impact on separation of concerns and, for example, unit testing.
For different reasons there is no "absolute proper way" of doing persistence. One of the reasons is that each way of tackling it has different tradeoffs; which one is better for you project is hard to tell. The other important reason is that languages evolve, so a new language feature can improve the way frameworks handle things. So, instead of looking for the perfect way of doing it you may want to consider different ways of approaching OO persistence assuming that you want so use a relational database:
Use the Active Record pattern. What you have done so far looks like is in the Active Record style, so you may find it natural. The active record has the advantage of being simple to grasp, but tends to be tightly coupled with the DB (of course this depends on the implementation). This is bad from the separation of concerns view and may complicate testing.
Use an ORM (like Doctrine or Propel). In this case most of the hard work is done by the framework (BD mapping, foreign keys, cascade deletes, some standard queries, etc.), but you must adapt to the framework rules (e.g. I recall having a lot of problems with the way Doctrine 1 handled hierarchies in a project. AFAIK this things are solved in Doctrine 2).
Roll your own framework to suite your project needs and your programming style. This is clearly a time consuming task, but you learn a lot.
As a general rule of thumb I try to keep my domain models as independent as possible from things like DB, mainly because of unit tests. Unit tests should be running all the time while you are programming and thus they should run fast (I always keep a terminal open while I program and I'm constantly switching to it to run the whole suite after applying changes). If you have to interact with the DB then your tests will become slow (any mid-sized system will have 100 or 200 test methods, so the methods should run in the order of milliseconds to be useful).
Finally, there are different techniques to cope with objects that communicate with DBs (e.g. mock objects), but a good advise is to always have a layer between your domain model and the DB. This will make your model more flexible to changes and easier to test.
EDIT: I forgot to mention the DAO approach, also stated in #MikeSW answer.
HTH
Stop second-guessing yourself. A static method getActiveEntries() is a perfectly reasonable way to solve this problem.
The "enterprisey" solution that you're looking for would probably involve something along the lines of creating a GuestbookEntryFactory object, configuring it to fetch active entries, and executing it. This is silly. Static methods are a tool, and this is an entirely appropriate job for them.
GetActiveEntries should be a method of a repository/DAO which will return an array of GuestBookEntry. That repository of course can implement an interface so here you have easy testing.
I disagree in using a static method for this, as it's clearly a persistence access issue. The GuestBookEntry should care only about the 'business' functionality and never about db. That's why it's useful to use a repository, that object will bridge the business layer to the db layer.
Edit My php's rusty but you get the idea.
public interface IRetrieveEntries
{
function GetActiveEntries();
}
public class EntriesRepository implements IRetrieveEntries
{
private $_db;
function __constructor($db)
{
$this->_db=$db;
}
function GetActiveEntries()
{
/* use $db to retreive the actual entries
You can use an ORM, PDO whatever you want
*/
//return entries;
}
}
You'll pass the interface around everywhere you need to access the functionality i.e you don't couple the code to the actual repository. You will use it for unit testing as well. The point is that you encapsulate the real data access in the GetActiveEntries method, the rest of the app won't know about the database.
About repository pattern you can read some tutorials I've wrote (ignore the C# used, the concepts are valid in any language)
Now that I have read an awfull lot of posts, articles, questions and answers on OOP, MVC and design patterns, I still have questions on what is the best way to build what i want to build.
My little framework is build in an MVC fashion. It uses smarty as the viewer and I have a class set up as the controller that is called from the url.
Now where I think I get lost is in the model part. I might be mixing models and classes/objects to much (or to little).
Anyway an example. When the aim is to get a list of users that reside in my database:
the application is called by e.g. "users/list" The controller then runs the function list, that opens an instance of a class "user" and requests that class to retrieve a list from the table. once returned to the controller, the controller pushes it to the viewer by assigning the result set (an array) to the template and setting the template.
The user would then click on a line in the table that would tell the controler to start "user/edit" for example - which would in return create a form and fill that with the user data for me to edit.
so far so good.
right now i have all of that combined in one user class - so that class would have a function create, getMeAListOfUsers, update etc and properties like hairType and noseSize.
But proper oop design would want me to seperate "user" (with properties like, login name, big nose, curly hair) from "getme a list of users" what would feel more like a "user manager class".
If I would implement a user manager class, how should that look like then? should it be an object (can't really compare it to a real world thing) or should it be an class with just public functions so that it more or less looks like a set of functions.
Should it return an array of found records (like: array([0]=>array("firstname"=>"dirk", "lastname"=>"diggler")) or should it return an array of objects.
All of that is still a bit confusing to me, and I wonder if anyone can give me a little insight on how to do approach this the best way.
The level of abstraction you need for your processing and data (Business Logic) depends on your needs. For example for an application with Transaction Scripts (which probably is the case with your design), the class you describe that fetches and updates the data from the database sounds valid to me.
You can generalize things a bit more by using a Table Data Gateway, Row Data Gateway or Active Record even.
If you get the feeling that you then duplicate a lot of code in your transaction scripts, you might want to create your own Domain Model with a Data Mapper. However, I would not just blindly do this from the beginning because this needs much more code to get started. Also it's not wise to write a Data Mapper on your own but to use an existing component for that. Doctrine is such a component in PHP.
Another existing ORM (Object Relational Mapper) component is Propel which provides Active Records.
If you're just looking for a quick way to query your database, you might find NotORM inspiring.
You can find the Patterns listed in italics in
http://martinfowler.com/eaaCatalog/index.html
which lists all patterns in the book Patterns of Enterprise Application Architecture.
I'm not an expert at this but have recently done pretty much exactly the same thing. The way I set it up is that I have one class for several rows (Users) and one class for one row (User). The "several rows class" is basically just a collection of (static) functions and they are used to retrieve row(s) from a table, like so:
$fiveLatestUsers = Users::getByDate(5);
And that returns an array of User objects. Each User object then has methods for retrieving the fields in the table (like $user->getUsername() or $user->getEmail() etc). I used to just return an associative array but then you run into occasions where you want to modify the data before it is returned and that's where having a class with methods for each field makes a lot of sense.
Edit: The User object also have methods for updating and deleting the current row;
$user->setUsername('Gandalf');
$user->save();
$user->delete();
Another alternative to Doctrine and Propel is PHP Activerecords.
Doctrine and Propel are really mighty beasts. If you are doing a smaller project, I think you are better off with something lighter.
Also, when talking about third-party solutions there are a lot of MVC frameworks for PHP like: Kohana, Codeigniter, CakePHP, Zend (of course)...
All of them have their own ORM implementations, usually lighter alternatives.
For Kohana framework there is also Auto modeler which is supposedly very lightweight.
Personally I'm using Doctrine, but its a huge project. If I was doing something smaller I'd sooner go with a lighter alternative.
I am working on extending an existing PHP application. Unfortunately for me, the existing app is a mess. It's all spaghetti code with raw mysql_* calls. Groan. No way that I am going to do that in the parts that I am extending.
So, I am looking for a simple ORM of DBAL that I can easily drop in and start using. Desired features:
It must work on an existing database schema. Preferably with minimal or no additional configuration. The existing database schema is the same quality as the existing PHP code (no sensible naming conventions, not normalised, etc.). I don't want to spend days converting the database schema manually into annotated object properties a la Doctrine 2.
It must be able to work alongside the existing raw mysql_* queries. I have no idea how hydrating ORMs like Doctrine 2 or Propel behave when scripts are manually manipulating the data in the database behind their backs, but I assume it's not pretty.
It must run on PHP 5.2.x. I'd love to use PHP 5.3 but I have zero interest in going over the existing 125K lines of spaghetti code mess to make sure it runs on PHP 5.3.
Relationships not required. In the few places I need to get to relational data, I'll be happy to call an extra find() or query() or whatever myself.
Bonus points if it has some trigger support (e.g. beforeSave, afterSave). Not a requirement, but just nice to have.
Edit: Someone put me out of my misery. I just found out that the 125K lines of spaghetti code also changes the database schema. E.g, add an extra option somewhere and a whole slew of ALTER TABLE statements start flying. I could probably fill a year's worth of TheDailyWTF with this codebase. So, one more requirement:
Must be able to cope with a changing database schema automatically (e.g. adding columns).
I have been looking at a few solutions, but I am unsure how well they would work given the requirements. Doctrine 2, RedBeanPhp and the like all require PHP 5.3, so they are out. There's a legacy version of RedBeanPhp for PHP 5.2.x but I don't know if it would work with a messy, existing database schema. NotORM looks okay for getting data out but I don't know if it can be configured for the existing database schema, and how you can easily put data back into the database.
Ideally I would like something simple. E.g:
$user = User::find($id);
$user->name = 'John Woo';
$user->save();
Or:
$articles = ORM::find('article')->where('date' => '2010-01-01');
foreach ($articles as $article) {
echo $article->name;
}
Any tips or even alternative solutions are welcome!
I use...
http://github.com/j4mie/idiorm/
it has an active record implementation too in the form of Paris.
With regard to your edit. Idiorm copes with changing schemas and the syntax almost exactly matches the type you want in your question.
How well did you look into Doctrine? I am using Doctrine 1.2 for these kind of things. Quite easy to setup, allows you to start off with an existing schema. It automatically figures out the relations between tables that have foreign key constraints.
It has extensive trigger and behaviour support, so the bonus points can be spent as well, and it has relational support as well, so your additional queries are not necessary. It has beautiful lazy loading, and it comes with a flexible query language (called DQL) that allows you to do almost exactly the same stuff that you can do in SQL in only a fraction of the effort.
Your example will look like this:
/* To just find one user */
$user = Doctrine::getTable('User')->findOneById($id);
/* Alternative - illustrating DQL */
$user = Doctrine_Query::create()
->from('User u')
->where('u.id = ?',array($id))
->fetchOne();
$user->name = 'John Woo';
$user->save();
It must be able to work alongside the existing raw mysql_* queries. I have no idea how hydrating ORMs like Doctrine 2 or Propel behave when scripts are manually manipulating the data in the database behind their backs, but I assume it's not pretty.
Well, that is technically impossible to auto-manage; a SQL database is simply not pushing back stuff to your ORM, so to update stuff that was changed in the background, you need to perform an additional query one way or the other. Fortunately, Doctrine makes this very easy for you:
/* #var User $user */
/* Change a user using some raw mysql queries in my spaghetti function */
$this->feedSpaghetti($user->id);
/* Reload changes from database */
$user->refresh();
I am currently working on a little application:
The structure follows in some way the MVC pattern.
For short it has the basic things, Models, Controllers etc.
Now I am sitting here and do not know whether :
1.
The SQL database is only managed by a model through methods the programmer gives him like: "Hey we have name record so we need a getName() method".
OR
2.
The model dynamically creates the whole database and methods, using a XML file, with which even a non-programmer can design a database.
And should the model class check every/a single request whether it is a valid request e.g. getName() won't work on the houses_tbl, and if it is not valid it does not perform the query, and sends back an error message instead?
I have absolutely no idea how to handle my model class, which structure it should follow and how much the programmer should have to put into a new model so it works as he wants it to work.
Major points:
perfomance (which way saves the most perfomance)
KISS (which way is simple enough, so a second team mate can understand my logic)
extendability (can I extend the structure)
Check these Data Source Architectural Patterns: Table Data Gateway, Row Data Gateway, Active Record, Data Mapper. For code examples to these patterns in PHP, you could check Zend_DB_*.
Which pattern you should pick depends on your application. If you are doing a simple CRUD application, you might want to use Row Data Gateway. If you are building an application with a lot of business logic from a certain domain, you will likely pick a different one.
Just remember that the M in MVC is not just the Persistence layer. The model is the heart of your application. Controller and View are just an end to your application. Further reading by Rob Allen and Matthew Weier O'Phinney.
As for your major points, I suggest to just stick to general established practises. UnitTest your code, write meaningful code and document it, favor aggregation over composition, capsule and separate concerns, code against an interface, refactor, etc.
Why not statically create the objects etc. during development from the database. i.e. use some Object-Relational-Mapping ?
That way you create your Person object from (say) the database schema. It creates a getName() accessor, and the rest of your code compiles against that. If you remove/rename the name field, then the generated code changes and consequently stuff doesn't compile. Catching these errors early will save a lot of grief.
This question details some PHP/ORM options. I confess I've not checked these to see if they're entirely what you want, but hopefully they should point you in the right direction.