2

I'm developing a PHP application and I find myself doing basically the same code for, say, creating an object based on a form filled by the user.

The objects are of different classes, but the process is mostly the same: take the data from the form, apply validation, save/return error.

Is there a way to automatize this process? I ask also because I intend to write a public API and use the same code to do those operations, instead of just copy/pasting.

I thought of making a kind of Factory Method pattern that receives the type and the data from the form (or any array), create an instance and set the data, testing the validation afterwards (each object knows how to validate their own fields). And that for each of the other CRUD operations as well.

Is that feasible/good practice? Should I just repeat the similar code? There are any other way to do it?

For the record, I'm using ORM already (Doctrine). Still, I think that a lot of create functions with pretty much the same code (a bunch of set*) is something too repetitive.

7

If you're not already using an ORM, you're probably doing it wrong, because you're not taking advantage of the leverage that an ORM can provide to the practice of writing CRUD methods.

However, there's a bit of history to all this, so I'm now going to tell you a little bedtime story.

In the beginning, there were SQL databases, and life was good. Web sites were pretty sparse little affairs, and everyone got along by writing data access code by hand.

Then the wolly mammoths came.

enter image description here

No, not that wooly mammoth.

This woolly mammoth. Databases that encompass an entire business domain:

enter image description here

Suddenly, data access code written by hand didn't cut it anymore. So we invented ORM's, code-generation programs that produced one class for each table, complete with CRUD methods. It's a lot of code, but you didn't have to write it, did you?

Great story, huh bro? Well, not exactly.

You see, someone came along and said "Why do I need to know database theory, when I could just write my classes and then have the ORM generate my tables for me?"

OK, but now you're gonna have to write all of those classes by hand, aren't you?

Which brings us to the question you asked, which essentially is this: why can't I just write a function that accepts a type T, and returns an object of type T, like this?

public T Read(int id); // C#, for those of you so challenged.

Sigh. Well, you can, actually. It's called a Generic Repository. If you want to find out how to build one, you can look here. It starts with something like this:

public function select($table, $where = '', $fields = '*', $order = '', $limit = null, $offset = null)
{
    $query = 'SELECT ' . $fields . ' FROM ' . $table
           . (($where) ? ' WHERE ' . $where : '')
           . (($limit) ? ' LIMIT ' . $limit : '')
           . (($offset && $limit) ? ' OFFSET ' . $offset : '')
           . (($order) ? ' ORDER BY ' . $order : '');
    $this->query($query);
    return $this->countRows();
}

...and builds on that humble beginning (and other functions to round out the CRUD) to create a complete generic repository. Add some IoC to it, and you'll have something that any Architecture Astronaut would consider worthy enough to take to interstellar space.

  • Wow, this is more than I expected, thanks for answering. I'm already using ORM (Doctrine, to be exact). Even though I don't use "queries", the code seems repetitive to me anyway, because the task is the same. Still, this repository thing seems to be pretty much what I thought of doing. – George Marques Mar 11 '14 at 19:38
  • 1
    @GeorgeMarques: I included some detailed history because (in my opinion) generic repositories come dangerously close to implementing an "inner platform." The problem, of course, is that you're still calling a method, but now you're doing it in a Type Parameter instead of calling a specific method, and now you'll most likely have to cast the returned object to something meaningful before using it. All in all, I'm not entirely sure it's worth the trouble. – Robert Harvey Mar 11 '14 at 19:41
  • @RobertHarvey I've worked someplace we had a generic repository as we allowed end users to override our code via their own DLLs and metadata to reference them. This enabled us to do some amazing things long before any of our competitors could even dream of some of the stuff we were doing, but now with all the updates to C# and supporting libraries it's solidly an inner platform situation now. Even worse it simply won't work in a reasonable manner with many of the newer practices that have improved over the years. So the only way to advance is the slow painful process of slowly ripping it out. – RualStorge Aug 19 '14 at 17:17
  • @RualStorge: Can you be more specific? Are you referring to Entity Framework? Your strategy didn't suddenly stop working just because Microsoft got sophisticated. – Robert Harvey Aug 19 '14 at 17:53
  • 1
    No the strategy still works, and on a principal level still makes a lot of sense and gives us an advantage in our market, however; the way it was implemented is vintage 90s. Since then changes to stuff like Entity Framework and changes in the languages and libraries available have made much of our functionality essentially obsolete. (they can do what we did better) The problem we have is almost all our code is customizable, which is great for our customers, but once it's heavily customized by clients our ability to change becomes limited. So the Generic Repositions is all but untouchable now. – RualStorge Aug 19 '14 at 18:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.