Читаем мануалы — об одном секрете include

    Для тех, кто приходит в мир PHP с С или других языков зачастую бывают откровением некоторые особенности языка, которые описаны в документации, но, тем не менее, часто ускользают из виду.

    Сегодня я хочу рассказать о нестандартном (с точки зрения большинства программистов) использовании оператора include в PHP

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

    Для того, чтобы получить «значение файла» достаточно во включаемом файле, как в функции, использовать оператор return. Тогда становятся возможными такие конструкции:

    a.php:
    $ret = 'aaa';
    return $ret;


    b.php:
    $b = include('a.php');
    echo $b; // Displays 'aaa'


    Для чего это может быть нужно?


    На личном опыте я нашел два вполне практических и практичных варианта применения этого «выверта».

    1. Построение блоков.

    Во многих CMS, ведущих свое родство от Nuke — это и XOOPS и RunCMS и новый форк Ronny CMS используется модульно-блочная структура. Модуль реализует некий функционал, а выводит свой контент в блоки, из которых и формируется страница.

    Сделано это обычно следующим образом. Каждый модуль имеет список блоков, а для блока задается включаемый файл и функция, выводящая контент:
    $block[0]['file'] = 'block_file.php';
    $block[0]['func'] = 'show_func';


    Соответственно где-то внутри CMS происходит что-то вроде
    include($module . $block[0]['file']);
    echo $block[0]['func']();


    Таким образом мы имеем лишний уровень абстракции и, что более страшно, — возможность коллизии имен функций.

    Рациональнее использовать возможность оператора include возвращать значение из включаемого файла:
    echo include($block[0]['file']);
    , что позволит упростить код и избавиться от опасности совпадения имен функций.

    Подобный подход применим не только в блоках CMS, но и везде, где требуется разделение программы на функциональные модули.

    2. Использование в конфигах

    Просто проиллюстрирую кодом:

    config.php:
    $config['host'] = 'test.com';
    $config['user'] = 'test';
    $config['pwd'] = 'tESt';
    return $config;


    test.php:
    $params = include('config.php');

    Все примеры условные и служат лишь для иллюстрации

    P.S. Ранее эта тема уже поднималась, например здесь: habrahabr.ru/blogs/php/39034, но я подумал, что ничего плохого в повторении не будет.

    P.P.S. Вопрос про значение, возвращаемое include и про конструкции вида $$a я использую на собеседовании с программистами. Решающего значения они не имеют, конечно, но позволяют понять, насколько глубоко человек знает используемый язык.

    Средняя зарплата в IT

    113 000 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 5 123 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 33

      +7
      Спасибо кеп!
        +4
        Да уж. Секрет. Ага.
          +1
          Не секрет — все написано в мануале.

          Но Вы не представляете, сколько «программистов», приходящих на собеседование и на работу, этого не знают…

          Может кому-то из них статья будет полезна?
            +3
            У Вас же есть прекрасный пример под рукой (хабратопик, на который Вы ссылались, где описывался ранее include). Соберите факты, которые, как Вы полагаете, могут быть упущены из виду программистами, и опубликуйте. А так получается, что и сам «секрет» давно всем известен, да еще и был ранее описан здесь…
              0
              Я же могу это делать постепенно? Сегодня статья, завтра, послезавтра?
          +3
          > что позволит упростить код и избавиться от опасности совпадения имен функций.
          это, простите, каким-же образом?

          во всех ваших примерах, мало того, что все импортируемые сущности попадают в локальное/глобальное пространство имен, так еще и память расходуется 2 раза.
          на саму переменную, и на присвоенную копию, если приспичит ее изменить.
            0
            >>это, простите, каким-же образом?

            Вы давно смотрели в код нюкоподобных CMS? Там двадцать функций с названиями вида «block_show()» — норма, а не исключение. Уходя от необходимости объявлять функции, мы уходим от опасности совпадения их имен. А уж имя файла гарантированно уникальное.

            >>во всех ваших примерах

            Примеры условные.
              0
              как __возврат значения инклюдом__ поможет избежать конфликта имен? — никак.

              не использовать функции можно и без возврата значений инклюдами.
              просто инклюдим — и все!
                0
                Вы уж простите, но не понял, если честно, что Вы имели в виду под «просто инклюдим — и все!». Не можете пояснить кодом?
                  0
                  вместо

                  a.php

                  пишем просто
                  a.php

                  и вызываем
                  index.php
                    0
                    парсер не лох.
                    разрабы хабра — мудаки.
            +1
            Честно говоря нужность этой возможности крайне сомнительна. Любой язык имеет не очевидные особенности которые редко кто юзает. Знать их полезно, блеснуть ими на собеседование, тоже круто. Но за реальное использование их в продакшен коде — нужно отрывать руки :)

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

            Тем ни мене — спасибо, я не знал о такой возможности. :)
              +1
              Насчёт ненужности — ну как сказать. Я так конфиги инклюдю :)
                +1
                Что же, пожалуй соглашусь, что _технически_ для конфигов этот прием имеет смысл.
                Я говорю скорее об общепринятости подхода.
                Какие плюшки это дает? Из минусов — у людей которые буду поддерживать ваш код после вас, этот прием может вызвать недоумение. Но может быть есть плюсы которые я не вижу и сам начну так делать после вашего ответа… :)
                  0
                  Ну а что мешает Вам совмещать оба подхода?

                  Делаете класс для работы с конфигами.
                  Внутри он работает так, как быстрее и проще, используя на «полную катушку» все возможности языка. А наружу смотрит красивыми интерфейсами, геттерами и сеттерами, чтобы ява-программисты не сошли с ума -))
                    0
                    Ни чего не мешает, вы правы. Я вообще не религиозен в плане кода. Если чтото работает и это возможно поддерживать — почему бы не использовать. :)

                    Но я скорее хотел увидеть от вас плюсы подключения конфигов таким образом, чем спорить и доказывать что я прав :) Знания новых подходов и чужой опыт для меня ценнее абстрактной правоты.
                      +1
                      У меня была статья в песочнице, в которой я попробовал профилировать разные варианты хранения конфигов.

                      С огромным отрывом победил метод unserialize(file_get_contents($file)) Описанный здесь метод — кажется на втором месте.

                      Если интересно — могу достать из черновиков, дополнить и опубликовать.
                        0
                        Мммм, а вот за этр спасибо!
                        unserialize(file_get_contents($file))
                        Точно так же хранит конфиги Kohana — теперь понятно почему.

                        Да, думаю ваша статья будет интересной — особенно для высоких нагрузок.

                        Думается мне что если сделать,
                        unserialize(apc_fetch($config_key))

                        то будет еще быстрее. Хотя не принципиально — файловый кеш еще ни кто не отменял.
                          0
                          Достал, опубликовал.

                          Не претендую на серьезность исследования, но цифры показательны.
                –1
                Простите за «холиварный» подход, но ООП нужно использовать там, где предполагается использование объектов.

                Является ли визуальный блок на странице у клиента сущностью-объектом на сервере, у которого есть время жизни, свойства и методы, процедуры создания и уничтожения, родители и потомки — для меня очень большой вопрос.
                  +3
                  Нюк, не самый лучший представитель того что есть на ПХП. И вы предлагаете, фактически, процедурный подход (ну, точнее модульный). Я видел очень мало хороших продуктов с таким подходом. Дрюпал — приятное исключение.
                  У меня был опыт (хороший друг попросил — сам бы не полез) с «чудесным» продуктом oscommerce (кстати достаточно известным и распространенным), где «плагины» устанавливались примерно как «в файле таком то, после строки Х вставить такие то строки». Я не шучу.
                  Конечно я не буду говорить что ООП, сам по себе поможет сделать хорошую архитектуру. Но сейчас по нему много материалов и просто прочтение GoF уже даст много идей для хорошей и правильной архитектуры.
                  Так что с точки зрения проектирования — ООП подходит лучше.

                  Если же говорить о производительности, то я уже не раз выражал свою точку зрения. Если ваше приложение упирается в производительность ПХП, это значит ПХП вам не подходит и инструмент реализации был выбран не верно.

                    +1
                    Нюк — ужасный представитель, ловите плюс.

                    Но я живу в реальном мире. И в нем зачастую используются далеко не идеальные подходы и технологии.
                      0
                      О прекрасно вас понимаю… У самого душа кровью обливается, кода ради дедлайна приходится просить команду делать неидеальное решение.

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

                      Как я уже сказал, трюк интересный, спасибо :) Знать о нем стоит. Но вот пользоваться — лично я остерегусь.
                        0
                        Ну в таком случае и оператор "++" можно называть трюком -))

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

                        Все ее неприятие, как я подозреваю, идет только лишь от того, что подобной возможности нет в других языках, считающихся на хабре «более правильными»…
                          0
                          Мне кажется у нас просто немного разные подходы. В смотрите на код сам по себе. Это вполне здравый подход.
                          Я смотрю, на код, на то как его поддерживать ближайшие 2-3 года и как это делать если человек написавший его уйдет из фирмы. Да, я немного прагматик и параноик в этом плане.

                          Относительно "++" я отвечу так. Если усредненный уровень разработчика, на которого у моей текущей компании есть бюджет, вдруг поглупеет, и перестанет понимать этот синтаксис, я попрошу людей в команде не использовать "++". Хотя конечно, лучше сменить место работы… :)
                          Знаю звучит странно, но мое мнение код это просто способ достичь цели. :)
                        • НЛО прилетело и опубликовало эту надпись здесь
                        +1
                        много красивых слов, призваных показать вас как грамотного разработчика.
                        на деле — ты знаешь много слов, но не видишь за ними смысла.

                        ООП — это парадигма разработки.
                        инклюды в пхп — это синтаксис языка. немного другой уровень абстракции.

                        Ты просто не понимаешь, о чем говоришь…

                        заинклюдь-ка мне файлик, исключительно средствами ООП, без инклюдов, реквайров…
                        а, да, у тебя же есть file_get_contents() и eval()!!!
                          0
                          Откуда столько негатива? :)

                          Вам не кажется что, для реализации кода отрисовки бокса на странице вполне подходит патерн

                          Strategy? И конечно при его реализации, мне где ни будь да заюзаем include…
                          Но есть все же большая разница как именно мы используем include — как побочный инструмент (в моем случае) или как основной (в варианте топикастера).

                            –1
                            попытка лепить патерны к месту и не к месту говорит о том, что ты незнаешь, для чего они нужны.

                            патерны — это способ решать ПРОБЛЕМЫ.
                            если у тебя везде одни патерны — значит у тебя везде проблемы.

                            и что это за «основной» инструмент, что за «побочный»?
                            твое ООП — это обертка вокруг стандартных методов и функций языка.

                            научишься писать не используя весь этот шлак, где он не нужен — не будешь писать подобную ахинею.
                              0
                              Что вам ответить — вы просто раздавили меня интеллектуально.
                              Пойду учиться писать без богомерзких патернов.
                      • НЛО прилетело и опубликовало эту надпись здесь
                    • НЛО прилетело и опубликовало эту надпись здесь
                        –3
                        баян=)

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое