2015-10-27 6 views
0

У меня есть приложение на основе MVC с основным правилом URL-переписывания, которое делает URL-адрес таким образом: website/controller/action/id. id не является обязательным.В PHP, когда автозагрузка файлов, где PHP будет искать эти файлы?

Если пользователь вводит недопустимый action, он должен получить сообщение об ошибке, которое обрабатывается в классе ErrorController.

Все файлы моих классов требуются в файле autoloader, поэтому я не должен требовать их каждый раз, когда хочу создать объект. Я использую spl_autoload_register() для автозагрузки.

Проблема возникает, когда я пытаюсь ввести URL-адрес с недопустимым action. Например, для URL website/main/inde (вместо index) - должен быть создан экземпляр ErrorController.

Вместо этого, я получаю это две ошибки PHP:

Warning: require(!core/errorcontroller.php): failed to open stream: No such file or directory in D:\Programs\Wamp\www\fanfics\v0.0.2!core\autoloader.php on line 5

И

Fatal error: require(): Failed opening required '!core/errorcontroller.php' (include_path='.;C:\php\pear') in D:\Programs\Wamp\www\fanfics\v0.0.2!core\autoloader.php on line 5

Вот визуальный мои файлы (восклицательный знак перед папки core для поддержания его на вершине):

visual of my files

index.php:!

<?php 

require "!core/autoloader.php"; 

$loader = new Loader(); 

ядро ​​/ autoloader.php

<?php 

function autoload_core_classes($class) 
{ 
    require "!core/" . strtolower($class) . ".php"; 
} 

function autoload_controllers($class) 
{ 
    require "controllers/" . str_replace("controller", "", strtolower($class)) . ".php"; 
} 

function autoload_models($class) 
{ 
    require "models/" . str_replace("model", "", strtolower($class)) . ".php"; 
} 

spl_autoload_register("autoload_core_classes"); 
spl_autoload_register("autoload_controllers"); 
spl_autoload_register("autoload_models"); 

ядро ​​/ basecontroller.php

<?php 

abstract class BaseController 
{ 

    protected $model; 
    protected $view; 
    private $action; 

    public function __construct($action) 
    { 
     $this->action = $action; 
     $this->view = new View(get_class($this), $action); 
    } 

    public function executeAction() 
    { 
     if (method_exists($this->model, $this->action)) 
     { 
      $this->view->output($this->model->{$this->action}()); 
     } 
     else 
     { 
      // Here I create an ErrorController object when the action is invalid 
      $error = new ErrorController("badmodel"); 
      $error->executeAction(); 
     } 
    } 
} 

Если я пытаюсь требовать controllers/error.php специально - он работает отлично:

. 
. 
. 
else 
{ 
    require "controllers/error.php"; // With this line it works just fine 
    $error = new ErrorController("badmodel"); 
    $error->executeAction(); 
} 

После долгого поиска в Интернете, я понимаю, что есть проблема с include_path, но я не совсем понимаю. Как я могу решить эту проблему?

+0

Укажите автозагрузчик в каталог ваших классов, и он получит их. – Script47

+0

Я попытался переместить его в корень (вместе с 'index.php'). Все те же ошибки. :( – Sipo

+1

Зарегистрировать один автозагрузчик не 3. – Script47

ответ

1

Для каждой функции автозагрузчика рекомендуется проверить, существует ли файл, прежде чем вслепую попытаться включить/потребовать его. Автозагрузчики не должны бросать какие-либо ошибки и должны терпеть неудачу, чтобы они могли позволить очередному автозагрузчику в очереди попытаться автоматически загрузить необходимые файлы.

<?php 

function autoload_core_classes($class) 
{ 
    if (is_readable("!core/" . strtolower($class) . ".php")) 
     include "!core/" . strtolower($class) . ".php"; 
} 

function autoload_controllers($class) 
{ 
    if (is_readable("controllers/" . str_replace("controller", "", strtolower($class)) . ".php")) 
     include "controllers/" . str_replace("controller", "", strtolower($class)) . ".php"; 
} 

function autoload_models($class) 
{ 
    if (is_readable("models/" . str_replace("model", "", strtolower($class))) 
     include "models/" . str_replace("model", "", strtolower($class)) . ".php"; 
} 

spl_autoload_register("autoload_core_classes"); 
spl_autoload_register("autoload_controllers"); 
spl_autoload_register("autoload_models"); 
+0

Он устраняет ошибки, о которых я упоминал, но теперь появилась новая ошибка: «** Неустранимая ошибка: Class« ErrorController »не найден в D: \ Programs \ Wamp \ www \ fanfics \ v0.0.2 \! Core \ basecontroller. php в строке 52 ** « – Sipo

+0

Мой плохой. Я исправлю ответ. Я скопировал первый «is_readable» и заменил путь и не заметил, что вы делаете «str_replace» для следующих файлов. – apokryfos

+0

** Неустранимая ошибка: Class 'MainModel' не найден в D: \ Programs \ Wamp \ www \ fanfics \ v0.0.2 \ controllerlers \ main.php в строке 17 **. Но я думаю, что я решил решение, основанное на вашем ответе. Если я это сделаю, я отредактирую ваш ответ и приму его. :) – Sipo

0

PHP ищет включения путей определяются в собственности include_path. Для командной строки вы можете проверить его значение с помощью:

php -i | grep include_path 

для веб-проверить его:

phpinfo() 

В любом случае вы можете изменить значение в php.ini.

Я использовал для chdir() в корне проекта в моей единственной точке входа, а затем включил файлы с относительным путем от root. Это работает, потому что include_path обычно содержит текущий каталог "."

+0

Можете ли вы добавить пример, пожалуйста? – Sipo

+0

Я имел в виду: в apache я переписываю каждый запрос в одну точку входа, скажем/my/app/path/index.php, и здесь я вначале добавляю что-то вроде * chdir (__ DIR __) *. Так что каждое последующее включение может быть сделано как относительное от/my/app/path/ – Jack

+0

Still doesn Не работай. :( – Sipo