Конструктор PHP выполняется до того, как аргументы для вложенных переменных могут быть предоставлены - PullRequest
0 голосов
/ 30 апреля 2009

Перво-наперво, вот небольшой фрагмент кода, который поможет объяснить мою проблему:

<?php
class foo {

    public $title;

    __construct{

        echo "<html>\n";
        echo "<head>\n";
        echo "<title>".$this->title."</title>\n";
        echo "</head>\n";
        echo "<body>\n";

    }

    /**
    *
    * I get $title from index.php
    *
    */
    public function setTitle( $title )
    {

        $this->title = $title;

    }


    __destruct{

        echo "</body>\n";
        echo "</html>\n";

    }

}
?>

Вы, наверное, уже заметили, что этот код создаст заголовок well,. Да, там пустое место. : -)

Для меня это действительно имеет смысл (даже если я этого не ожидал), потому что конструктор класса выполняется при создании объекта foo, что означает, что он не ждет, пока index.php предоставит аргумент для setTitle(), которая в свою очередь возвращает строку, которая заполняет $this->title.

Так что, если я действительно понимаю, что здесь происходит, что я могу сделать, чтобы обойти эту проблему? Должен ли я буферизовать вывод, используя встроенные функции буфера, а затем изменить сохраненный вывод с помощью предоставленной строки заголовка? Есть идеи?

Я бы очень, очень, очень хотел бы сохранить эту структуру, в которой конструктор и деструктор содержат этот повторяющийся код. Приятно, что эти функции не нужно нигде вызывать. Я понимаю, что некоторые разработчики могут считать это плохой практикой, но я все равно собираюсь делать это так, потому что я хочу, потому что я думаю, что это круто. Так что я на самом деле не ищу совета в этом аспекте, если только вы не чувствуете сильную мотивацию сообщить мне о моей глупости.

Так что, если у вас есть какие-либо советы / идеи / знания, которыми вы могли бы поделиться со мной, это было бы замечательно.

Спасибо, и не стесняйтесь не торопиться, потому что я думаю, что меня заставят оставаться внутри, прячась от злого свиного гриппа, который пришел в мой город, поэтому не спешите!

Ответы [ 4 ]

8 голосов
/ 30 апреля 2009

teh_noob. Послушай меня. Эти слова, которые я печатаю прямо здесь. Притворись, что я их говорю, и услышь слова, которые исходят из моих уст. Нет. НЕТ НЕТ НЕТ НЕТ НЕТ ! И нет, я не даю крысе задницу, как "круто" вы думаете, что это так.

Это один из тех неудачных сценариев, когда было бы короче перечислить «правильные» вещи в этом подходе, а не «неправильные». То есть ваши проблемы многочисленны . При этом я собираюсь рассмотреть только некоторые вещей, которые плохи в этой идее.

Во-первых, давайте просто обсудим ООП в целом. То, что вы делаете здесь, - моя самая нелюбимая вещь, которую я когда-либо видел: то, что я называю «программирование с помощью классов». То есть структурированное программирование под видом ООП, потому что использовалось ключевое слово класса. Если ты собираешься сделать это, не беспокойся. Просто используйте функции. Это простое и классовое насилие.

Классы являются объектными чертежами. Объекты поддаются инкапсуляции и реализации . Если вы на самом деле не поклонник Singleton паттерна , зачем создавать класс, который явно предназначен для создания только один раз? И прежде чем сказать: «Но Питер, нам помогает синглтон-паттерн !!! 1-й», постарайтесь понять, что на самом деле это не так уж и здорово . Кроме того, то, что вы здесь делаете, даже не является причиной, по которой люди обращаются к паттерну синглтона.

Второе - тема подклассов. Возможно, в какой-то момент в будущем вам понадобятся всплывающие страницы для вашего сайта. Или вам понадобятся версии для печати, которые больше, чем просто CSS. Может быть, вы даже захотите что-то, что совсем не HTML, как канал RSS. Что теперь? Какую другую работу, выполняемую в этом конструкторе, вам придется дублировать для работы этих новых типов страниц? Но что, если вы уже начали полагаться на подклассы для создания отдельных страниц? Теперь ты трахан. Конечно, вы можете вернуться и подключить шаблон декоратора , но зачем проходить всю эту работу, если эту проблему можно избежать с помощью глупого дизайна класса?

В-третьих, в первую очередь идея повторения HTML. Я в порядке с эхо для слова или два здесь, тег или три там. Но для больших кусков HTML это просто идиотизм. Имейте порядочность выходить в режим вывода и использовать HTML, который не заблокирован в строке. Мало того, что вам легче редактировать и читать, вы можете работать с ним в режиме WYSIWYG, если захотите.

В-четвертых, это плохо, плохо ломает SRP .

Пятое - этот тип нелепой конструкции приводит к тому типу проблем, которые вы пытаетесь решить здесь. Только вы не хотите знать, что решение состоит в том, чтобы удалить операторы echo из вашего конструктора. Есть ли способ обойти это? Конечно. На самом деле, есть даже больше, чем один. Я рекомендую любой из них? Нет, не совсем.

Наконец, давайте обсудим заголовки. Может быть, вы еще не узнали о них. Может быть, у вас есть и все равно. Но что произойдет, когда через 6 месяцев вы работаете над проблемой, и вы работаете внутри метода, который находится в глубине стека на 10 вызовов, и вы понимаете, что простая функция header() решит вашу проблему. Может быть, вам нужно настроить контроль кэша или вам нужно вручную установить код ответа - что угодно. Но угадайте, что вы не можете. Зачем? Поскольку ваш глупый конструктор выводит в браузер миллисекунду, которую он создал.

Итак, подведем итоги: НЕТ! Если только вы не достигли своей конечной цели, вы увидите, что некоторые из вас очень заняты ручной работой в Daily WTF .

Что я могу предложить, кроме предостережения? Может быть, часть нового направления? Что ж, отладка вывода достаточно сложна в хорошо скомпонованных системах, поэтому не начинайте с того, что стреляете себе в ногу, которая делает это неявно. Весь вывод вашей системы должен быть явным . Если вы хотите создать класс типа «страница», это нормально. Только не делай так .

class foo
{
    protected $title;
    protected $headers;

    public function setTitle( $title )
    {
        $this->title = $title;
    }

    public function addHeader( $header )
    {
        $this->headers[] = $header;
    }

    public function sendHeaders()
    {
        foreach ( $this->headers as $header )
        {
            header( $header );
        }
    }

    public function printPageHeader()
    {
        $this->sendHeaders();
        ?>
            <html>
                <head>
                    <title><?php echo $this->title; ?></title>
                </head>
                <body>
        <?php
    }

    public function printPageFooter()
    {
        ?>
                </body>
            </html>
        <?php
    }

    public function printPage()
    {
        $this->printPageHeader();
        $this->printPageFooter();
    }
}

$p = new foo;
$p->setTitle( 'Just Testing' );
$p->addHeader( 'Cache-control: no-cache' );
$p->printPage();
0 голосов
/ 30 апреля 2009

Вы можете передать заголовок в качестве аргумента в конструкторе?

0 голосов
/ 30 апреля 2009

schnalle: это плохая практика. это безумие.
the_noob: безумие ...?
the_noob: (кричит) ЭТО ... ЭТО ... МАЛЕНЬКАЯ РАМКА ИСПОЛЬЗОВАНИЯ!
the_noob: (запускает разделение кода и представление вниз по скважине)

Я не совсем понимаю, что вы хотите сделать, но просто передаю название в качестве параметра конструктору ...

<?php

class Title {
    public function __construct($title) {

        echo '<html><head><title>' . htmlspecialchars($title) . '</title></head><body>';
    }

    public function __destruct() {
        echo '</body></html>';
    }
}

?>

если вы действительно хотите, чтобы ваши объекты что-то печатали, я бы предложил магический метод __tostring (), чтобы вы могли просто echo ваш объект. но для тегов HTML ... все еще не полезно.

Я желаю вам удачи с вашей платформой, но вы либо гений (маловероятно) , либо парень, совершающий те же ошибки (почти), что делал каждый новичок (до появления MVC).

edit: Я не могу вам помочь. вы хотите прямой вывод при создании объекта, но вам нужно получить данные в объект до его создания. так что вы пытаетесь обойти что-то уродливое, чтобы сделать его еще хуже. это просто так не работает!
вы пытаетесь построить новый, лучший вид автомобиля, прикрепив колеса к живому ослу, а затем жалуетесь, потому что он как-то не сработал, как вы ожидали (осел на колесах! ууууу!), и теперь вы спрашиваете сообщество, как прикрепить задние фонари так, чтобы осел / машина ехали быстрее.

0 голосов
/ 30 апреля 2009

Вы можете сделать всю печать в деструкторе. Там все переменные известны. Однако (как вы сами сказали), я думаю, что это действительно очень плохая практика. Я бы посоветовал использовать файлы вида / шаблона (у вас все равно достаточно времени :)).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...