PHP OOP - Classes that need db access - php

I'm starting to write some PHP classes that are reusable across projects but had a quick question about handling dependencies.
I'm writing a pagination class that I want to grab results from a mysql database. Now obviously this will rely on a Database object/class. I have a custom written database class that I want to use but then I hit a problem. I was planning to pass the db object in as a paramter but of course, because it is my own db class - it will have custom methods that not everyone else will have.
So my pagination class might run:
$db->run_query($sql);
Obviously, someone else might have a db class that instead uses:
$db->query($sql);
What's the best way to deal with this? I could run my query before but then I'm making more work than I want to for the user. Is the lesser re-usability just something I'll have to live with if I want to make it a one-line command?
It's similar with other examples, so I may want a Page object to use an HTMLHelper but then the page class hits a wall in terms of it being easily reusable.
This is more for personal projects at the moment but releasing these classes is something that is likely to happen in the future.

Perhaps the response is :
What does it mean to "program to an interface"?
You may have to reconsider your conception.

Related

In PHP, how do I use classes to pull data from my database and cache it?

I've been learning how to use classes, and I've been glancing through the Wordpress documentation and the files themselves, and I noticed all the database calls are done through a single class (WPDB).
I'm just curious how all this is done. It's kind of hard to see the forest for the trees when looking at Wordpress code, as it's so large.
I guess what I'm after is I want to create something like a "Page" object built around a class that pulls the appropriate page from the database and caches all the information for later use.
So far I've learned to create an abstract class that extends a basic enumeration class and contains constant values of my permissions, roles, tasks, etc. I kind of understand it. So, that's the level of understanding I have so far.

Why separate Model and Controller in MVC?

I'm trying to understand the MVC pattern in Phalcon.
In my current application I only need ONE template file for each table. The template contains the datagrid, the SQL statement for the SELECT, the form, add/edit/delete-buttons, a search box and all things necessary to interact with the database, like connection information (of course using includes as much as possible to prevent duplicate code). (I wrote my own complex framework, which converts xml-templates into a complete HTML-page, including all generated Javascript-code and CSS, without any PHP needed for the business logic. Instead of having specific PHP classes for each table in the database, I only use standard operation-scripts and database-classes that can do everything). I'm trying to comply more with web standards though, so I'm investigating alternatives.
I tried the INVO example of Phalcon and noticed that the Companies-page needs a Companies model, a CompaniesController, a CompaniesForm and 4 different views. To me, compared to my single file template now, having so many different files is too confusing.
I agree that separating the presentation from the business logic makes sense, but I can't really understand why the model and controller need to be in separate classes. This only seems to make things more complicated. And it seems many people already are having trouble deciding what should be in the model and what should be in the controller anyway. For example validation sometimes is put in the model if it requires business logic, but otherwise in the controller, which seems quite complex.
I work in a small team only, so 'separation of concerns' (apart from the presentation and business logic) is not really the most important thing for us.
If I decide not to use separate model and controller classes,
what problems could I expect?
Phalcon's Phalcon\Mvc\Model class, which your models are supposed to extend, is designed to provide an object-oriented way of interacting with the database. For example, if your table is Shopping_Cart then you'd name your class ShoppingCart. If your table has a column "id" then you'd define a property in your class public $id;.
Phalcon also gives you methods like initialize() and beforeValidationOnCreate(). I will admit these methods can be very confusing regarding how they work and when they're ran and why you'd ever want to call it in the first place.
The initialize() is quite self-explanatory and is called whenever your class is initiated. Here you can do things like setSource if your table is named differently than your class or call methods like belongsTo and hasMany to define its relationship with other tables.
Relationship are useful since it makes it easy to do something like search for a product in a user's cart, then using the id, you'd get a reference to the Accounts table and finally grab the username of the seller of the item in the buyer's cart.
I mean, sure, you could do separate queries for this kind of stuff, but if you define the table relationships in the very beginning, why not?
In terms of what's the point of defining a dedicated model for each table in the database, you can define your own custom methods for managing the model. For example you might want to define a public function updateItemsInCart($productId,$quantity) method in your ShoppingCart class. Then the idea is whenever you need to interact with the ShoppingCart, you simply call this method and let the Model worry about the business logic. This is instead of writing some complex update query which would also work.
Yes, you can put this kind of stuff in your controller. But there's also a DRY (Don't Repeat Yourself) principle. The purpose of MVC is separation of concerns. So why follow MVC in the first place if you don't want a dedicated Models section? Well, perhaps you don't need one. Not every application requires a model. For example this code doesn't use any: https://github.com/phalcon/blog
Personally, after using Phalcon's Model structure for a while, I've started disliking their 1-tier approach to Models. I prefer multi-tier models more in the direction of entities, services, and repositories. You can find such code over here:
https://github.com/phalcon/mvc/tree/master/multiple-service-layer-model/apps/models
But such can become overkill very quickly and hard to manage due to using too much abstraction. A solution somewhere between the two is usually feasible.
But honestly, there's nothing wrong with using Phalcon's built-in database adapter for your queries. If you come across a query very difficult to write, nobody said that every one of your models needs to extend Phalcon\Mvc\Model. It's still perfectly sound logic to write something like:
$pdo = \Phalcon\DI::getDefault()->getDb()->prepare($sql);
foreach($params as $key => &$val)
{
$pdo->bindParam($key,$val);
}
$pdo->setFetchMode(PDO::FETCH_OBJ);
$pdo->execute();
$results=$pdo->fetchAll();
The models are very flexible, there's no "best" way to arrange them. The "whatever works" approach is fine. As well as the "I want my models to have a method for each operation I could possibly ever want".
I will admit that the invo and vokuro half-functional examples (built for demo purposes only) aren't so great for picking up good model designing habits. I'd advise finding a piece of software which is actually used in a serious manner, like the code for the forums: https://github.com/phalcon/forum/tree/master/app/models
Phalcon is still rather new of a framework to find good role models out there.
As you mention, regarding having all the models in one file, this is perfectly fine. Do note, as mentioned before, using setSource within initialize, you can name your classes differently than the table they're working on. You can also take advantage of namespaces and have the classes match the table names. You can take this a step further and create a single class for creating all your tables dynamically using setSource. That's assuming you want to use Phalcon's database adapter. There's nothing wrong with writing your own code on top of PDO or using another framework's database adapter out there.
As you say, separation of concerns isn't so important to you on a small team, so you can get away without a models directory. If it's any help, you could use something like what I wrote for your database adapter: http://pastie.org/10631358
then you'd toss that in your app/library directory. Load the component in your config like so:
$di->set('easySQL', function(){
return new EasySQL();
});
Then in your Basemodel you'd put:
public function easyQuery($sql,$params=array())
{
return $this->di->getEasySQL()->prepare($sql,$params)->execute()->fetchAll();
}
Finally, from a model, you can do something as simple as:
$this->easyQuery($sqlString,array(':id'=>$id));
Or define the function globally so your controllers can also use it, etc.
There's other ways to do it. Hopefully my "EasySQL" component brings you closer to your goal. Depending on your needs, maybe my "EasySQL" component is just the long way of writing:
$query = new \Phalcon\Mvc\Model\Query($sql, $di);
$matches=$query->execute($params);
If not, perhaps you're looking for something more in the direction of
$matches=MyModel::query()->where(...)->orderBy(...)->limit(...)->execute();
Which is perfectly fine.
Model, View and Controller were designed to separate each process.
Not just Phalcon uses this kind of approach, almost PHP Frameworks today uses that approach.
The Model should be the place where you're saving or updating things, it should not rely on other components but the database table itself (ONLY!), and you're just passing some boolean(if CRUD is done) or a database record query.
You could do that using your Controller, however if you'll be creating multiple controllers and you're doing the same process, it is much better to use 1 function from your model to call and to pass-in your data.
Also, Controllers supposed to be the script in the middle, it should be the one to dispatch every request, when saving records, when you need to use Model, if you need things to queue, you need to call some events, and lastly to respond using json response or showing your template adapter (volt).
We've shorten the word M-V-C, but in reality, we're processing these:
HTTP Request -> Services Loaded (including error handlers) -> The Router -> (Route Parser) -> (Dispatch to specified Controller) -> The Controller -> (Respond using JSON or Template Adapter | Call a Model | Call ACL | Call Event | Queue | API Request | etc....) -> end.

Symfony2: Transformation of database records for displaying

I have rather theoretical question about proper approach of using Symfony though I believe the approach is to be same for any other PHP framework.
I have tariff objects stored in database. I want to provide a cost model for each tariff basing on user input.
My initial approach was to create an array, one's each element would contain data from corresponding tariff object and calculated data. All of that was done in controller's action method.
Later I have created another class CostModel and then created an array CostModel[], which than was passed to $this->render() method. Again it's done in controller.
This approach works well enough. However, since I have not much experience with Symfony, I have doubts that this approach - performing calculations in controller - is good one.
Is there any better way for this?
Well, your question could have more than one answer as it is very opinion-based.
What I can say without any doubt about controller's code is that the less it is the more is good. Why I said that? Because controller code isn't reusable, because controllers are made to "connected" views and business logic (keep attention: connect, not encapsulate) and a general rule that I follow when I develop with Symfony2, is to write, into controller, lines of code for "objects" that are directly accessible from controller (form, request, views, and so on); all code that isn't related to these concepts should be migrated elsewhere.
Your solution is a good starting point but we cannot judge as we haven't more details and we don't know the architecture of your software. What can I say - and I hope you already know - is that you can pass to render (so to view templating system; I suppose you are using twig) directly the ArrayCollection you've obtained querying the database (so basically you don't neeed CostModel[] array). So, maybe, your approach is good but not the best: maybe you can take advantage of Repository facility, write a good query that can extract and calculate data for you (in a more optimized way) and use repository directly into controller. That way you could at the same time, migrate code where it should stay, write less number of code lines, do some optimitazion (or better, let Doctrine do for you) and you don't need to create a brand new class (model).

Choosing which classes to use in a php OOP design

I run an arcade site and over the past few years it's had many features added, it's got to the point where procedural programming just looks way too complicated and adding new features or making simple design modifications can be very tricky.
Therefore I've decided to try and recode the site from the ground up with the same features but in an OOP format.
The issue I have is picking the classes, I understand OOP and how it should work but always seem to have trouble getting started. I am unsure whether I should be trying to make functions for classes such as a user class with log in user function or if the user class should just be to add/update/show user details and the log in part would be better in a system class?
At the moment I've started with the following class and functions but do they fit in this category?
<?
class User {
var $userId,
$username,
$userRole,
$userEmail;
function isLoggedIn(){
}
function login($postusername, $postpassword)
{
}
function increaseLoginCount(){
}
function logout(){
}
}
?>
I could then have something like the following in a page.php .. (connect class not shown)
<?
$db = new Connect;
$db->connect();
$user = new User;
if(!$user->isLoggedIn())
{
echo "Please Log In.";
if($_POST['user'])
{
$user->login($_POST['username'], $_POST['password']);
}
}
else
{
if($_POST['logout'])
{
$user->logout();
exit;
}
echo $user->username." Logged In.<br />";
}
?>
But then the site would have pages to show game categories and I don't know where the displayGames() function would fit as it's not a single game so wouldn't go in the 'Game' class?
I've tried to find 'real world' examples but php code showing me how to make an elephant change colour or dance doesn't really help ...
Let's start with some textual analysis, highlights by me:
I run an arcade site and over the past few years
Think about how much you are able to cope with and what you are dealing with. Also understand that over the years you have gained specific knowledge about running arcade site. You have gained profession in your area. Never underestimate your own position and assets, it's the base you're operating from and you will introduce changes to. This includes your site's userbase.
it's had many features added, it's got to the point where procedural programming just looks way too complicated and adding new features or making simple design modifications can be very tricky.
If systems grow, they become more and more complicated. That's not specific to procedural programming only, it's a matter of fact. As you're running the site now for many years, you know how things changed, especially in the area how the user interfaces with your site.
Therefore I've decided to try and recode the site from the ground up with the same features but in an OOP format.
It's said that it could be possible to use OOP techniques to make re-useable software, there is (and can not be) any proof of this.
But there are only very few examples in commercial software development where re-writing the whole application from scratch was a success. Very few. The rules of commercial software development might not apply in your specific case, so just saying.
Think twice before you recode the site. Doing a lot of work only to achieve the same is somewhat fruitless and can be disappointing. Instead probably look more specifically which of your current design is introducing the biggest problem you would love to change.
It is possible with PHP to mix procedural and object-oriented style, which can be especially useful when you have legacy code (a common definition of legacy code is code w/o automated tests).
The issue I have is picking the classes,
I try to rephrase that: For what write classes for?
I understand OOP and how it should work but always seem to have trouble getting started.
The beginning is always the hardest step. You're in the position ready to make decisions now, but you can't look into the future. Reduce the risk by eliminating the most risky part. You've probably started to ask a question here to gain some feedback to base your decisions on, but that will probably not reduce the burden and might lead to confusion. However, getting educated is most often a good thing.
I am unsure whether I should be trying to make functions for classes such as a user class with log in user function or if the user class should just be to add/update/show user details and the log in part would be better in a system class?
That highly depends on the nature of your application and the nature of the user. Probably the most of your script only need to know if a user is concrete or anonymous (an anonymous user has not logged in), it's ID, name or nickname.
The application should provide that user to any consuming component, so each command/script does not need to deal with a) obtaining users information and handling users (like logging in), b) verifying if the component is valid for the user (access control). That should be placed somewhere else, e.g. in the application controller­PofEAA.
Each of your scripts/commands that has the application controller object, can ask for the user and just interact with the user.
However this is just technically speaking. Deal with the fact of yourself being unsure, work with that information. Try to better formulate your concrete problem, list pros and cons for a specific way of solving it, get away from concrete code again before starting to code. Then compare pros and cons. Try to make things more simple and less complicated.
Probably write down in simple words what should be happening instead of writing code.
At the moment I've started with the following class and functions but do they fit in this category**?**
Your code is quite bare, so it's hard to say much about it - especially as I don't know what your arcade site is (and what the category is you write about). It's still good for an example probably. What can be seen in your classes is that you tightly integrate everything with each other.
For example you start with the DB. That's common, because the DB is a central component for any application. The application needs the DB to operate on. However you want to keep things loosely coupled so that all your commands can be run with some other DB or a new user object that is connected with some even other DB than the rest of your application's data objects.
$application->getDB();
As the user is such a central subject in each application, it should have a very simple interface. All the glory details about authentication, retrieving of the users properties etc. should be delegated into another class/component, so that you can change the implementation where users are stored and how they authenticate:
/**
* #package command.modules.games
*/
function ListGamesCommand(Request $request, Response $response)
{
$application = $request->getApplication();
$user = $application->getSession()->getUser();
$games = $application->getModels()->build('games');
$games = $games->findByUser($user);
$response->setProp('games', $games);
}
As this example shows, you can add the functionality when you need it. E.g. as long as your application does not need to actually log in users, why care about how it's written now?
Create a factory that is producing the user for the application object - whatever it will need now or in the future (see the Two Piles of Objects in The Clean Code Talks — Inheritance, Polymorphism, & Testing). If you then need the authentication, either add it to the session object or the user object interface.
The authentication itself would be implemented in a class of it's own anyway, the Authenticator. So you can review your interfaces later on as well, by moving the invocation of authentication from session to user or whatever. Only a fraction of your commands will need to deal with these specific task and as all new code is under automatic tests as you want to rewrite and benefit from OOP, you have ensured that all the places are covered and properly re-factored.
Same is true for accessing request variables. If you want to make use of the benefits of OOP - which is highly connected with indirection (and each layer of indirection comes with a price) - you should first of all make your base classes operate on specific data and not on any data (like globals and superglobals, I've seen $_POST in your example code).
So enable your new code to operate on a request and deliver a response (Input - Processing - Output):
$request = new Request($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES, $_ENV);
$response = new Response;
Example taken from the BankAccount - Sample application used for PHPUnit training
Now everything below this can operate on a Request and a Response object - process input and turn it into output. The domain command (your scripts/commands that do the thing) do not need to care any longer about extracting input from the HTTP request like using $_POST or $_GET they can take it directly from the Request - or if you write a class of commands of it's own - this can be even more tailored. And some commands can operate on requests and responses of their own.
The next big topic is the user-interface. You write you want to:
I've decided to try and recode the site from the ground up with the same features but in an OOP format.
I already wrote that such a doing can be fruitless. To have a benefit of OOP code would mean that the next time you change your code, you're still able to re-use components. As software changes constantly, this time now is already the next time. So you want to already re-use existing code. I assume one part of your existing code is the output logic. So the existing output logic needs to interface with the exemplary Request and Response above.
I bet you love websites. You love to make them just work and look great. You've build your site over the years and even not everything is like you wish it to be, you don't want to drop it. So it's crucial for your re-write that you don't destroy everything but you can preserve it's working form from now to the future (See as well Preserve a Working Application; last point of the list).
In webapps the view is such a crucial part. If you loose the view, your site will loose it's identity. If you change too much of it, your site will loose users that are comfortable with using it today.
If you break it,
will you even notice?
can you fix it?
On the other hand you want your application code (the features, the functionality) to not be that tightly bound to it any longer to have a benefit in rewriting your code. As you want to rewrite your application, let's take a look:
.---------. .-------------.
| website | ---> [interface in ] ---> | application |
| user | <--- [interface out] <--- | |
`---------´ `-------------´
As this schema shows, to make your application more independent to whatever the interaction looks like (can be a website, a (smartphone) GUI or the ticketing system), the application code should be replace-able. You don't want to code the logic to obtain a users games for example for every type of user-interface in the new application code, but you did in the old application code.
Taking the User object as an example here. How it authenticates and where it is stored shouldn't be something your new application commands code are concerned about. It's just there if the command needs it. Not globally but specifically if the command asks for it.
Where-as the registration and lost password procedures are part of your existing application and continue to exist.
Now you need to bring the old and the new code together.
So you will probably start with an interface for HTTP requests and a HTTP response. The view kicks in with that Interface Out. You assign/pass all needed data for the view via that interface, your application does not know the view any longer. You don't deal with any CSS, Javascript or HTML code within your new application code. That's just the sugar on top for the output. Your application should interface as well via console/telnet in plain text or as a remote XMLRPC service, AJAX endpoint - whatever.
So you can probably just generalize your view code and inject variables to it. To write a view layer could be as simple as including a PHP file. It operates on variables that are available within it's scope. It can make use of "helper" functions (template macros) that are available in it's scope. It can make use of view model objects. It's even possible to write your own language for the view (templating language, a Domain Specific Language (DSL)).
But this is only possible if you create an interface that allows the application code to do so.
So what you now do is to move away the HTTP/HTML/CSS/JS from your application into an adapter of it's own. That adapter is able to formulate the generic command that can be passed to any application via interface in.
The application will only take care to execute the command and deliver it's response via interface out. So you have two domains now: Your application and the website.
You can start to create these two new domains and then offer an interface in and out for your legacy code and one for your new code.
You also have "two" applications next to each other. They are finally bound together (invisible in their own code) with your database which takes care that the data of your site is in order. And that's what the database is for. Separate the data from your code, so you can change your code over time.
Also if you want to re-code, draw a border between the existing code and the new code.
Good luck! And I hope reading this will show you some options for your specific case. Also take note that you don't turn your controllers into just another facade to the database. Probably you've got the best benefits (don't know your concrete biggest problem) by using a lightweight HTTP abstraction and a view layer only as it might be that your application is for websites only.
Because as in HTTP / PHP:
[Interface In] Plain Text HTTP request
[Application] Free to go
[Interface Out] Plain Text HTTP response
You normally need only some functionality to parse the input and build the output.
Additionally not using fat models has the benefit that you access your data quickly and sequentially, e.g. if you don't need to pass the output at once (buffered, one-block), you can make of the benefit to stream the output to the server.
You should decide which parts are important to refactor for your application, not OOP or not. Like procedural, OOP needs to be done well as well. If you today run into problems by writing procedural code, OOP code might not the answer to your problem. The need to write better procedural code might be it. Just saying, it's not easy to refactor an application and you should identify the actual problem first.
If you break it, will you even notice?
If you break it, can you fix it?
The crucial part is that you can notice and that you have everything at hand to do the fix.
Get your website under test, so you can say if changing code here or there is actually doing good. Be able to turn any change back if it comes to light it's not working (better).
That done you can easily decide about a new feature or not. As long as you don't need to introduce new features, there is no need to change anything in how you write features. And until there, you can't plan for the new features.
So better think twice before re-writing your application. As written, this can kill the project.
See as well: How to implement MVC style on my PHP/SQL/HTML/CSS code?­SO Q&A
OOP is all about identifying areas of responsibility and constructing self-contained units of code intended to handle one, and only one, of those areas. A general rule of thumb is that each object in your system should embody an equivalent object or concept in the real world but that's not always true as you need to also worry about abstract things that are needed to make your system work (I mean abstract here in the sense that they don't represent an item of business logic, but are still needed to make the system work. I don't mean abstract classes, which is something else altogether).
For example, in your gaming site, you're probably going to have to deal with Games, Users, Moderators, Accounts, Reviews, Comments and so on. Each of these should be a class in its own right, and every instance of that class should represent a particular User, Game, Comment and so on.
But classes have areas of responsibility, and a stated above, a class should deal with its area of responsibility and nothing else. Rendering a page is not the responsibility of any of the object classes mentioned above. This is where the classes that don't represent the entities of your system come in. You'll probably need a class for a Page, a class for a Session, a class for database connections (though PHP has you covered there already with PDO and some of the other DB modules such as mysqli).
To render a page you'd use an instance of a page class. You'd pass it a reference to the logged in user object, references to any game objects you'd want it to display, and so on. Then you'd have it render the actual HTML. The Page class doesn't need to know anything about the inner workings of the objects you pass it, other than about the APIs that those objects expose (known in OOP circles as the object's protocol, in otherwords their public methods and properties). A (very basic) Page class might look like this:
class Page
{
private $user = NULL;
private $games = array ();
public function setUser (User $user)
{
$this -> user = $user;
}
public function getUser ()
{
return ($this -> user);
}
public function addGame (Game $game)
{
$this -> games [] = $game;
}
public function getGames ()
{
return ($this -> games);
}
public function generate ()
{
$user = $this -> getUser ();
$games = $this -> getGames ();
$pageFile = '/path/to/a/php/script/representing/the/page/markup.php';
require ($pageFile);
}
public function __construct (User $user, array $games)
{
$this -> setUser ($user);
foreach ($games as $game)
{
$this -> addGame ($game);
}
}
}
The actual markup.php script would probably look something like this:
<html>
<head>
<title>Games page for <?php echo ($this -> user -> getName ()); ?>
</head>
<body>
<p>Hello, <?php echo ($this -> user -> getName ()), here are your games.</p>
<?php if (count ($this -> games)) { ?>
<ul>
<?php foreach ($this -> games as $game) { ?>
<li><?php echo ($game -> getName ()); ?>: your best score is <?php echo ($game -> getHighScore ($this -> user)); ?></li>
<?php } ?>
</ul>
<?php } ?>
</body>
</html>
As you might have noticed, if you use this approach then your application's modules will tend to fall into one of three categories. Your business logic objects like User and Game, your display logic like the markup.php file, and the third group that serves as a form of glue logic and coordination like the Page class.
Whilst in this particular case it's specific to your site, if you were to generalize this approach further it would fall into a design pattern known as MVC, which stands for Model, View, Controller (well actually it's closer to a pattern called PAC for Presentation, Abstraction, Controller, but it's almost always called MVC in the PHP community for some reason, so we'll just say MVC for now). A pattern is a generalization of a class of problems that programmers run into on a regular enough basis that having a toolkit of pre-made solutions is handy.
In the case of your gaming application, User and Game are models, Page is a controller, and markup.php is a view. If you substitute a different markup.php script into this code you can use it to present the exact same data in a completely different way, say as an XML file for example. You could also use the same models with a different controller to get them to do different things. The important thing to keep in mind here is that models should not concern themselves with how they are being used, that way they can be used in different ways depending on what the controller needs to achieve.
As MVC is a pattern, there are already toolkits that exist to build MVC (though they aren't really MVC ;) ) applications in PHP. These are called frameworks. There are plenty to choose from out there, such as Symfony, CodeIgnitor, Zend Framework and so on. The most popular framework these days is Zend, though I'm not personally a fan of it. (I would say that the beta versions of Zend Framework 2 do look a lot better than the current version of the framework though).
I hope this has been helpful for you. I know OOP can be daunting at first. It does require you to change your way of thinking as a programmer, but don't worry, it will come with enough practice.
All the members in the user class look like they belong there. It's important to separate the gui code from other code, I'd put displayGames() in some sort of gui class.
GordonM's post is a good one to get you started. I would certainly recommend using an established framework to get you started - they do a lot of the heavy lifting for you and will help you get used to OOP within PHP. Personally, if you're using PHP5.3 I'd recommend Symfomy2 but that's purely a personal preference. What I would also suggest is you get hold of a copy of the "Gang of Four" book. It's pretty much essential reading and although it comes mainly from a non-request-driven-environment background many of the patterns are still relevant in PHP.

php oop MVC design - proper architecture for an application to edit data

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.

Categories