Asked  7 Months ago    Answers:  5   Viewed   26 times

I've seen code written where almost all non-route related code is passed to a model. I have also seen code where all database persistence is handled by a model, but non-DB processing is handled by the controller.

Which is the better approach?

 Answers

40

The line between controller and model is actually quite clear.

Model is your application's heart. It contains the business/domain logic required to solve the problem your application was written for. The Model is usually layered into several other layers, e.g. persistence, services, domain, etc. It's a common misconception that the Model is just the database, as much as it is a common misconception that the database should be an ActiveRecord.

The controller (and the view) are part of the presentation layer. A controller's sole responsibility is to receive and handle user input directed towards your application and delegate this to the appropriate parts in the model. Nothing more. It should not handle complex application flow or code of your problem domain. You want controllers to be skinny and models fat with logic. The Model should not know about either C or V and you should be able to swap out V and C for a different presentation layer without having to touch your M.

See MVC Excerpt in Patterns of Enterprise Application Architecture

Wednesday, March 31, 2021
 
Jesse
answered 7 Months ago
46

Ok I'm just gonna start by saying I'm no expert in PHP and I recommend using a framework such as symphony to do your routing, but here is one possible solution that you could use.

function regexPath($path)
{
    return '#' . str_replace([":int:", ":string:"], ["d+", ".+"], $path) . '#';
}

function parseRequestedView($url)
{
    $ressource_requested = explode('/', trim($url, '/'));


    // define our routes, and the indices that each route will use (from the exploded url)
    // this could be defined as another parameter or as a member of the class
    $routes = [
        regexPath("article/:int:/comments/show") => [0,  2, 3,  1], // will return array(resource[0], resource[2], resource[3], resource[1]), etc
        regexPath("article/:int:/show")          => [0, -1, 2,  1], // -1 will return a null
        regexPath("archive/show")                => [0, -1, 1, -1]
    ];


    // go through each route, checking to see if we have a match
    foreach ($routes as $regex => $indices)
    {
        if (preg_match($regex, $url))
        {
            // it matched, so go over the index's provided and put that data into our route array to be returned
            foreach ($indices as $index)
            {
                $route[] = $index > -1 ? $ressource_requested[$index] : null;
            }

            // include the post data (not really nessesary)
            $route[] = $_POST; // unnessesary to pass $_POST data through function, because it is global

            return $route;
        }
    }

    return null; // or some default route maybe?
}

$route = parseRequestedView("article/13/comments/show");

echo '<pre>';
print_r($route);
echo '</pre>';

/* returns:
Array
(
    [0] => article
    [1] => comments
    [2] => show
    [3] => 13
    [4] => Array // this is our $_POST data
        (
        )

)
*/
Wednesday, March 31, 2021
 
PLPeeters
answered 7 Months ago
13

I personally subclass both Zend_Db_Table_Abstract and Zend_Db_Table_Row_Abstract. The main difference between my code and yours is that explicitly treat the subclass of Zend_Db_Table_Abstract as a "table" and Zend_Db_Table_Row_Abstract as "row". Very rarely do I see direct calls to select objects, SQL, or the built in ZF database methods in my controllers. I try to hide the logic of requesting specific records to calls for behind Zend_Db_Table_Abstract like so:

class Users extends Zend_Db_Table_Abstract {

    protected $_name = 'users';

    protected $_rowClass = 'User'; // <== THIS IS REALLY HELPFUL

    public function getById($id) {
        // RETURNS ONE INSTANCE OF 'User'
    }

    public function getActiveUsers() {
        // RETURNS MULTIPLE 'User' OBJECTS            
    }

}

class User extends Zend_Db_Table_Row_Abstract {

    public function setPassword() {
        // SET THE PASSWORD FOR A SINGLE ROW
    }

}

/* CONTROLLER */
public function setPasswordAction() {

    /* GET YOUR PARAMS */

    $users = new Users();

    $user = $users->getById($id);

    $user->setPassword($password);

    $user->save();
}

There are numerous ways to approach this. Don't think this is the only one, but I try to follow the intent of the ZF's design. (Here are more of my thoughts and links on the subject.) This approach does get a little class heavy, but I feel it keeps the controllers focused on handling input and coordinating with the view; leaving the model to do the application specific work.

Tuesday, July 27, 2021
 
Juriy
answered 3 Months ago
74

Two things:

myLine.SnapsToDevicePixels = true;
myLine.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
Wednesday, August 11, 2021
 
mpen
answered 3 Months ago
17

It is tempting to put everything in the AppDelegate, but if you start doing this, then your AppDelegate will be full of reference hacks. If you are doing a strict MVC, then you should have 3 things:

  • A Model
  • A View Controller (Only for view logic)
  • A Controller (For coordinating between the view and the model)

So for example, I have a model Foo and a Foo controller. I would have:

  • Foo.m (Model)
  • FooViewController.m (Displays a Foo)
  • FooController.m (Controls the logic)

And finally, to answer your question, I would store my references to Foo's in the foo Controller. I like to use singletons for my controllers, but thats just me. If you do use a singleton, you can just do something like this: [[FooController sharedInstance] listOfFoos] to get your Foo's

Sunday, September 12, 2021
 
Saint Robson
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :