0

I am writing my own php mvc framework (just for training). The question is how to handle exception when the requested controller doesn't exist? Should I call 404 class or create and show new View from Router? I'll be glad if you have any advices for me! Here are my autoload.php:

function __autoload($class)
{

$filename = __DIR__ . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
if (file_exists($filename))
{
    require $filename;
}
else
{
    throw new \Exception('The file doesn\'t exists!');
}

}

and Route.php:

namespace App;

class Route
{

public static function start ()
{

    $controller_name = 'News';
    $controller_action = 'Index';


    if (isset($_GET['furl']))
    {

        // Getting rid of spaces
        $url = str_replace(' ', '', $_GET['furl']);

        if (substr($url, -1) == '/')
        {
            $url = substr($url, 0, count($url) - 2);
        }


        $arr = explode('/', $url);

        foreach($arr as &$value)
        {
            $value = strtolower($value);
            $value = ucfirst($value);
        }


        $controller_action = $arr[count($arr) - 1];

        unset($arr[count($arr) - 1]);

        $controller_name = implode('\\', $arr);                        

    }

    $controller_name = '\App\Controllers\\' . $controller_name;

    try
    {

        $controller = new $controller_name();

    }
    catch (\Exception $e)
    {
        //HELP ME PLS!
    }

    $controller->action($controller_action);

}

}
sudoLife
  • 3
  • 4
  • 1
    I suggest you look into [class_exists](http://php.net/manual/en/function.class-exists.php) and [method_exists](http://php.net/manual/en/function.method-exists.php) instead of offloading that responsibility to the autoloader. Also [__autoload](http://php.net/manual/en/function.autoload.php) is deprecated, use [spl_autoload_register](http://php.net/manual/en/function.spl-autoload-register.php) instead, or look into using composers autoloader. – Lawrence Cherone Jan 06 '18 at 19:55
  • I suggest you stop reinventing the wheel and in turn use well-written frameworks that embrace good practices and patterns. You won’t learn anything valuable by writing such code. Begin by installing the Composer, no one writes autoloaders nowadays. – Mike Doe Jan 06 '18 at 20:25
  • @mike I wanna know how does it work, that's why I'm writing this code. – sudoLife Jan 06 '18 at 20:48
  • @LawrenceCherone I'm sorry, but the question was how to view 404 page right.. I will also use your advice about autoloaders, thanks – sudoLife Jan 06 '18 at 21:02
  • That does not make any sense. You won’t learn much this way. Good luck anyway. – Mike Doe Jan 06 '18 at 21:19
  • @aendeerei Can you write your comment as an answer? 'Cause I want to mark it as an anwer, because it helped a lot. – sudoLife Jan 07 '18 at 09:09

1 Answers1

1

No matter how many web frameworks, routers, autoloaders, etc are there already: keep doing what you think it's right for you and suitable to your momentarily understanding level, in order to LEARN. Actually, by confronting yourself with problems arised along the process of implementing yourself different parts of your application, you will not only gain the opportunity to learn and discover new things, but also to learn how and what to study in the already existing frameworks' design.

Study the PHP Standard Recommendations (the ones marked as "accepted"). Especially PSR-1,2,4,7. They are used by many frameworks and PHP projects. Read FAQs to find out more about the project itself.

Autoloader:

The PSR-4 provides a link with examples at the document end.

@mike suggested, that you should use the Composer autoloader. I agree with him and I strongly recommend it to you too. BUT I suggest you to do this only after you correctly implement and make use of your own autoloader (PSR-4 conform). Why? You definitely need to learn how the autoloading process works. And in some future situations you will still need your own autoloader implementation, even after Composer is installed and running.

Also be aware that you must not raise any exceptions from autoloader itself!

Router:

Btw, your class should be called "Router".

The router should not be responsible for validating the controller class/file and the action, nor for calling the action. These tasks are part of the "front controller" responsibilities. Your router should just return the components resulted after parsing, e.g. "exploding" the request URI ($_GET['furl']), in some form (as a Route object (with them as properties), as array, etc). These components are the controller name, the action name, the action parameters list (NB: the action parameters are not the query string parameters). The front controller uses them further to validate/access the controller class/file and its action and to call the action.

But please note that a router works actually in other way. In short: it matches (e.g. compares) the request method (GET, POST, etc) and the request URI against an existing (e.g. predefined by you) list of route definitions. A route definition contains the infos related to a specific controller, action, etc. If the HTTP method and the request URI "correspond" to one of the route definitions, then the router returns the matched definition's components to the front controller (in some form: as object, as array, etc).

For more details describing this principle see:

Front controller:

It can be a class, but it can also be just vanilla code in the entry point of your app (index.php, bootstrap.php, etc). In the latter case, the front controller code should reside in a file outside of the document root of the app. For example in a bootstrap.php file, which is to be just included in index.php - whereas index.php resides inside the document root.

"controller/action not found" specific handling:

If a controller, or an action is not found/valid, then call a predefined action (for example displayError) of a predefined Error controller, which informs the user that, for a specific part of his request (actually of his provided request URI), no resource was found.

For example, consider that the user provided the request URI www.example.com/books/show/12. Conform to your app workflow the controller is Book, the action (e.g. the controller's method) is show and the action parameter is 12 (the value is passed as argument to the show method and defined as $bookId parameter in it). But, if the controller class is not defined, or no controller file exists, then the front controller should call the action displayError of Error controller, which should display a message like No resource found for your 'book' request. A similar info should be displayed when the show method is not yet defined in the Book controller.

Note that, if the Error controller or its action is not found/valid, then the PHP engine raises a corresponding error/exception. If you follow the next links I provided, you'll end up implementing three custom error/exception handling functions (referenced by set_error_handler, set_exception_handler and register_shutdown_function, respectively). They will catch and handle the described situation properly.

To read: Manage the errors of a framework

General error/exception handling in MVC:

Here are some good resources:

Other MVC related resources:

P.S: Avoid the use of statics, globals, singletons. Why? Read here and here, for example.

Good luck.

Community
  • 1
  • 1