При написании моей собственной фреймворк PHP, нужно несколько мнений / предложений по подходу - PullRequest
2 голосов
/ 28 января 2011

Прежде чем я начну, этот фреймворк не должен конкурировать с Zend, Symfony, Cake или любым другим фреймворком. Это в первую очередь личный проект, так что я могу испытать некоторые вкусности PHP 5.3, испытать новые методы и дать мне возможность попробовать что-то в соответствии с моей идеей. Я также пытаюсь сделать этот каркас как можно более легким и уменьшить количество ненужных методов получения и установки. Теперь о проблеме.

Большая часть фреймворка выполнена, в первую очередь все основные классы, необходимые для его работы. Проблема возникает на точке входа приложения. Я хочу, чтобы все приложение запускалось через один основной объект, который разветвляется. Базовый объект будет расширен классами для управления средами, конфигурацией, реестром, автозагрузкой, маршрутизацией и т. Д. И т. Д. Вы можете увидеть этот «базовый» объект ниже, он точно называется Application.

https://github.com/titon/titon/blob/42c88e36c29e3d8c697306fe68be18b3a8fd2e70/titon/source/Infrastructure.php

$app = new \titon\source\core\Application();

Идея заключалась в том, что из любой точки приложения вы можете получить доступ к основным объектам через эту переменную $ app. Пример:

(Я не могу опубликовать более 1 ссылки, поэтому перейдите в следующие каталоги на Github. /App/config/Setup.php и /app/modules/core/Bootstrap.php)

$app->environment->current();
$app->loader->includePath(array(__DIR__));
$app->registry->factory('titon\source\system\Controller');

Но теперь мы попадаем в проблему глобальных переменных, которую я не хочу использовать. Мне также нравится стараться избегать синглетонов.

public function foobar() {
    global $app; // Eww
}

Но я также не хочу использовать статические классы, так как я пытался использовать более ООП подход. Единственное решение, которое я могу придумать, - это использовать свойство статического класса для хранения экземпляра приложения и доступа к нему везде, но мне это не нравится. Или я могу снова и снова передавать объект его детям, но опять же, не поклоннику.

Core::$app->router->detect(); // Meh
$this->setApplication($this); // Mehher

Мне было любопытно, как Zend и Symfony подошли к этой проблеме. Но, просмотрев их исходный код, я не смог задом наперед разработать и определить правильную точку входа. Более того, казалось, что Zend будет создавать глобальные переменные повсюду (Zend_Config и т. Д.), Но я бы предпочел иметь управляющий объект. Symfony 2.0, я просто потерялся. Что касается Cake, Solar, Fuel, кажется, они используют статические классы для таких объектов.

Теперь мой основной вопрос: как бы вы решили это? Я хотел бы сохранить один объект для создания экземпляра и быть доступным везде, но это не кажется легким в обращении. Я готов переписать многие рамки, если это будет необходимо.

Ответы [ 3 ]

1 голос
/ 29 января 2011

Идея заключалась в том, что из любой точки приложения вы можете получить доступ к основным объектам через эту переменную $ app.Пример:

...

Но теперь мы попадаем в проблему глобальных переменных, которые я не хочу использовать.Мне также нравится стараться избегать синглетонов.

Это кажется мне противоречием.

Знаете ли вы почему вам не нужны глобальные переменные?Это потому, что вы где-то читаете, что глобальные переменные - это плохо?

И наоборот, знаете ли вы почему вам нужен центральный объект, доступный из любого места в вашем приложении?

Follow Up :

На случай, если неясно, это означало риторические вопросы.С архитектурной точки зрения глобальные переменные (в любой форме) стоят дороже .Некоторые говорят, что зло .Я думаю, что это немного упускает из виду - вам нужно некоторое количество глобальных переменных в любом приложении (по крайней мере, одна).Чтобы еще больше мутить воду, «глобальное» действительно относительное;Гораздо важнее рассматривать переменные как имеющие разные области видимости, где глобальная находится на одной противоположности континуума, а локальная, временная переменная - на другой.Если у вас есть один объект, содержащий все другие ваши объекты, то я бы рассматривал каждую из этих переменных как глобальные переменные, хотя они не могут быть таковыми в техническом смысле.Подумайте немного об этом.

Что касается серебряной пули, вы можете взглянуть на внедрение зависимостей .Это подход к избеганию глобальных переменных, который работает, но имеет определенную стоимость в виде сложности.

0 голосов
/ 29 января 2011

Лучшим решением для избежания глобальных переменных является внедрение зависимостей.Вам, вероятно, нужно создать какой-нибудь контейнер.Посмотрите библиотеку компонентов Symfony.

Вы также можете попробовать шаблон реестра.

0 голосов
/ 29 января 2011

Одна из старых нерешенных проблем PHP: невозможно определить суперглобальные переменные без использования такого расширения, как runkit.

Обычно я решаю это с помощью псевдо-реестра, то есть я определяю class R со всеми переменнымиЯ хочу сделать глобальное определение как public static $var.Я знаю, что это, вероятно, не подход ванильного ООП, но он хорошо работает.R::$var настолько коротка, насколько это возможно, я думаю.Все остальное, например внедрение зависимостей ($this->var) или синглтон (R::getVar()), длиннее.

...