Является ли $ view в MVP-программе MVC правильным использованием глобальных переменных?

Я понимаю, что глобальных переменных следует избегать в целом. Как новичок, я пытаюсь понять, является ли создание переменной $ view глобальной в динамической веб-программе, построенной по принципам MVC, одним из тех случаев, когда глобальные переменные – хорошая идея.

В моей программе я создаю $ view (как объект, содержащий пустой массив) в index.php, и превращаю его в глобальный в контроллерах, которые его используют.

Благодаря!

JDelage

Related of "Является ли $ view в MVP-программе MVC правильным использованием глобальных переменных?"

В моей программе я создаю $ view как пустой массив () в index.php и превращаю его в глобальный в контроллерах, которые его используют.

Зачем? Если вам нужен контроллер $view то просто передайте его через конструктор или сеттер. Зависимости от Globals можно всегда разрешать с помощью Injection Dependency .

 // index.php $view = array(); $controller = new Controller($view); $controller->doAction(); 

Кроме того, пожалуйста, пересмотреть, если представление должно быть просто массивом. В какой-то момент представление должно отображаться. Оказание – это ответственность, которую я увижу в представлении. Массив не может отобразить себя, поэтому я предполагаю, что вы делаете это в другом месте. Это было бы нарушением принципа единой ответственности . Я бы предпочел сделать что-то вроде ( упрощенного ):

 // index.php $view = new View; $controller = new Controller($view); $controller->doAction(); // controller.php ... public function doAction() { ... $this->view->setTemplate('/path/to/template'); $this->view->setVar('foo', 'bar'); $this->view->render(); } ... 

Глобальные переменные следует избегать , правда. Однако они полезны для хранения глобального состояния – это не приводит к межсоединению – как, в частности, к $ config array / object.

Но в вашем случае я не уверен, что $ view – хорошая идея. Во-первых, я считаю, что вы собираете выходные данные. «Просмотр» в MVC – это больше выходного шаблона, и я считаю, что ваш index.php есть? Если это так, то вы фактически собираете $ model. Неопределенный.
Теоретически чище передать эту переменную в контроллеры явно. Если это действительно только одна глобальная переменная, и вы обещаете не переусердствовать, передавая ее, как глобальное, это нормально.

Но вы также можете следовать указанному шаблону одноэлементности. Однако я бы рекомендовал процедурный вариант, потому что он чище:

 function view() { static $view; if (!isset($view)) { $view = new ArrayObject(); } return $view; } 

Таким образом, вы можете использовать $view=view(); локализовать его в своих контроллерах, продолжать использовать его как массив $view["xy"]= и как объект $view->xy= в то же время.
Или просто напишите print view()->title; в шаблоне.

Создание переменной global не является хорошей идеей при использовании шаблонов MVC в проекте. Существуют и другие решения, которые будут использовать ваш MVC более разумно.

Если у вас должно быть одно использование ресурса, используйте шаблон singleton . Что-то вроде

 class My_View { private $_instance; static public function getInstance() { if (null === self::$_instance) { self::$_instance = new self(); } return self::$_instance; } private function __construct() { } public function __clone() { trigger_error("Cannot make copy of this object", E_USER_ERROR); } // add public methods and/or properties here... } 

и получить этот объект просмотра в любом месте с помощью

 $view = My_View::getInstance(); 

Таким образом, у вас нет глобальных переменных, и вы используете лучшие методы OO.

Однако, как указывали другие, наличие одноэлементного представления не обязательно является хорошей идеей … Вероятно, лучшим вариантом было бы сделать ваш код диспетчера создающим новое представление и установить его на вызываемый контроллер, поэтому контроллер будет иметь доступный доступ и доступ к нему напрямую.

Представление (не являющееся одиночным) также может быть публичным свойством или доступным, хотя это общедоступный метод приложения singleton; My_Application::getInstance()->getView(); которые также могут содержать текущую конфигурацию, пути,

Имя, предложенное My_view является просто примером. Использование своего рода соглашения об именах помогает организовать код и помогает избавиться от всех тех, которые включают / требуют вызовов в заголовках скриптов. Это не в сфере вашего вопроса, однако для ясности я кратко объясню:

В вашем бутстрапе вы объявляете свою функцию автозагрузки (как определено в руководстве по PHP ):

 // My_Application.php located in /path/to/lib/My/Application.php class My_View { private $_instance; static public function getInstance() { if (null === self::$_instance) { self::$_instance = new self(); } return self::$_instance; } private $_basePath; public $view; private function __construct() { } public function __clone() { trigger_error("Cannot make copy of this object", E_USER_ERROR); } public function initAutoloader($base) { $this->_basePath = $base; spl_autoload_register(array($this, 'autoload')); } public function autoload($name) { require $this->_basePath . str_replace('_', '/', $name) . '.php'; } // get the application global view public function getView() { if (null === $this->view) { $this->view = new My_View(); } return $this->view; } } // perhaps have the parameter being a constant. Ig APP_BASE_PATH My_Application::getInstance()->initAutoload('/path/to/lib/'); 

И просто My_View файл '/path/to/lib/My/Application.php' и когда вы будете обращаться к My_View , функция load будет вызвана с $name = 'My_View' и функция просто потребует файл '/path/to/lib/My/View.php' для вас. Это не так много для одного файла, но если все классы являются такими пространствами имен, вам нужен только один ( Autoloader ), и все остальное загружается автоматически.

Решение этой проблемы, которое я видел, состоит в том, что контроллеры расширяются от базового контроллера. Внутри этого базового контроллера создается свойство $data ; новые данные представления затем добавляются к этому свойству. Например:

 class PageController extends BaseController { function IndexAction() { $this->data['title'] = "Page Title"; $this->data['content'] = "<p>Page content.</p>"; $this->render(); } } 

Метод рендеринга (который может быть загружен автоматически после запуска метода, а не явно) собирает шаблон, используя данные, хранящиеся в массиве $data .

Надеюсь, это поможет, и вы сможете реализовать рабочее решение.