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

StackOverflow https://stackoverflow.com/questions/805404

  •  03-07-2019
  •  | 
  •  

Вопрос

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

<?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";

    }

}
?>

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

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

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

В-четвертых, это плохо, плохо ломает рекомендуемая розничная цена.

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

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

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

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

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();

Другие советы

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

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

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).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top