Подключение файлов в PHP

30.07.2023 в 07:54
55005
+3583
loader

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

Архитектура программного обеспечения (англ. software architecture) — совокупность важнейших решений об организации программной системы. Архитектура включает:
– выбор структурных элементов и их интерфейсов, с помощью которых составлена система, а также их поведения в рамках сотрудничества структурных элементов;
– соединение выбранных элементов структуры и поведения во всё более крупные системы;
– архитектурный стиль, который направляет всю организацию — все элементы, их интерфейсы, их сотрудничество и их соединение.

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

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

Ну а вообще, давайте на примере. Но сначала давайте изучим одну «магическую» константу. Речь идёт о константе __DIR__. В ней содержится путь до директории, в которой находится текущий скрипт (скрипт, в котором эта константа была использована).

Давайте запишем в наш index.php следующий код:

<?php
echo __DIR__;

Результат этого кода:

C:\OpenServer\domains\myproject.loc\www

Вуаля, мы теперь знаем, в какой папке находится index.php. Мы будем всегда использовать магическую константу __DIR__ при указании путей подключаемых файлов. При этом в выражениях для подключения файлов следует избегать данных от пользователей, чтобы избежать хакерских атак под названием PHP-injections. Подробнее читайте здесь.

Ну а теперь вернёмся к основной теме урока. Создадим в директории с index.php ещё один файл с именем functions.php и заполним его следующим содержимым:

<?php

function isEven(int $x)
{
    return $x % 2 === 0;
}

Теперь вернёмся в index.php и запишем в него следующий код:

<?php

include __DIR__ . '/functions.php';

?>
<html>
<head>
    <title>Чётные и нечётные числа</title>
</head>
<body>
Число 2 <?= isEven(2) ? 'чётное' : 'нечётное' ?>
<br>
Число 5 <?= isEven(5) ? 'чётное' : 'нечётное' ?>
<br>
Число 8 <?= isEven(8) ? 'чётное' : 'нечётное' ?>
</body>
</html>

Надеюсь, никто не забыл, что можно вставлять PHP-код прямо внутри HTML? Об этом мы говорили в этом уроке. Только там мы использовали для вывода конструкцию вида:

<?php echo 2 + 2; ?>

Если во вставке нам нужно только вывести результат какого-то выражения, то её можно упростить до:

<?= 2 + 2; ?>

И если сейчас мы зайдём в браузере на URL нашего приложения, то увидим следующее:
Работа директивы include

Наше приложение успешно отработало, и основной код страницы у нас не содержит вспомогательных функций – они с помощью директивы include подключились в наш файл. Если говорить более детально – PHP-код из файла functions.php был вставлен в то место, где он был подключен с помощью директивы include.

Разница между require и include

Есть ещё одна директива для подключения файлов – require. Если вы сейчас замените include на require, вот так:

require __DIR__ . '/functions.php';

то ничего по сути не изменится – код отработает точно так же.

Однако между ними всё же есть разница. Она заключается в том, что если подключаемый файл не найден, то при include возникнет warning, но программа продолжит своё выполнение. А если подключаемого не окажется при попытке выполнить require, то произойдёт фатальная ошибка и скрипт завершит свою работу.

Давайте снова вернём директиву include, переименуем functions.php в abc.php и попробуем обновить страничку.

Ошибка подключения с типом warning

Получили ошибки разных типов. Первая из них – warning, сообщающий о том, что файл functions.php не найден. Но скрипт продолжил своё выполнение, а затем упал на строке 10 из-за того, что не была найдена функция isEven(), а это уже fatal error.
Давайте теперь заменим include на require и снова обновим страничку.
Фатальная ошибка при отсутствии файла

Теперь мы получили fatal error сразу на второй строке, приложение завершило свою работу на этом месте.

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

А include можно использовать для файлов, которые необязательно должны быть подключены (если без них можно продолжать выполнение кода). Пример: файл с кодом баннерной рекламы. Да, реклама не покажется, но зато сайт продолжит свою работу.

Как ещё можно использовать require и include

Помимо того, что можно подключать файлы с PHP-кодом, можно также подключать файлы, содержащие какой-то текст, или в частности HTML-код.

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

Зелёным цветом я выделил ту часть странички, которая будет изменяться.

Давайте для начала сверстаем наш шаблон. Надеюсь, все прошли курс по HTML. У меня получился вот такой код:

<html>
<head>
    <title>Заголовок страницы</title>
    <style>
        table, td {
            border: solid black 1px;
            border-collapse: collapse;
        }

        #layout {
            width: 800px;
            margin: auto;
        }

        #layout td {
            padding: 20px;
        }

        #sidebar {
            width: 300px
        }
    </style>
</head>
<body>
    <table id="layout">
        <tr>
            <td colspan="2">HEADER</td>
        </tr>
        <tr>
            <td id="sidebar">SIDEBAR</td>
            <td>CONTENT</td>
        </tr>
        <tr>
            <td colspan="2">FOOTER</td>
        </tr>
    </table>
</body>
</html>

Вот такая получилась у меня веб-страничка:
Свёрстанная страничка

Давайте теперь разобьём этот код на компоненты. Создадим 4 файла: header.php с шапкой файла, sidebar.php с боковой колонкой, content.php с основным содержимым страницы и footer.php для подвала сайта.

header.php:

<html>
<head>
    <title>Заголовок страницы</title>
    <style>
        table, td {
            border: solid black 1px;
            border-collapse: collapse;
        }

        #layout {
            width: 800px;
            margin: auto;
        }

        #layout td {
            padding: 20px;
        }

        #sidebar {
            width: 300px
        }
    </style>
</head>
<body>
    <table id="layout">
        <tr>
            <td colspan="2">HEADER</td>
        </tr>
        <tr>

sidebar.php:

<td id="sidebar">SIDEBAR</td>

content.php:

<td>CONTENT</td>

footer.php:

    </tr>
    <tr>
        <td colspan="2">FOOTER</td>
    </tr>
</table>
</body>
</html>

А теперь вернёмся в index.php и запишем в него следующий код:

<?php

require __DIR__ . '/header.php';
require __DIR__ . '/sidebar.php';
require __DIR__ . '/content.php';
require __DIR__ . '/footer.php';

Обновим страничку и увидим, что она по-прежнему работает. Только теперь она собралась из маленьких кусочков, каждый из которых отвечает за свою часть.

В подключаемых файлах мы можем использовать переменные, которые были определены до их подключения. К примеру, давайте в index.php добавим переменную $content:

<?php

$content = '<h1>Заголовок статьи</h1><p>Текст какой-то статьи</p>';

require __DIR__ . '/header.php';
require __DIR__ . '/sidebar.php';
require __DIR__ . '/content.php';
require __DIR__ . '/footer.php';

А в файле content.php выведем эту переменную:

<td><?= $content ?></td>

Давайте теперь снова обновим страничку:
Динамически сформированная страничка

Та-да! Наша страничка сформировалась динамически! Мало того, что она была собрана из разных компонентов, так она ещё и выводит значения из переменных.

Директивы require_once и include_once

Иногда нужно, чтобы файл подключился только один раз. Например, чтобы только однажды подключить файл с функциями. Для этого используются директивы require_once и include_once.

Давайте создадим файл config.php и запишем в него следующее содержимое:

<?php
echo 'Это просто заглушка вместо конфига.';

И теперь создадим файл test.php и напишем следующий код:

<?php

include_once __DIR__ . '/config.php';
include_once __DIR__ . '/config.php';
include_once __DIR__ . '/config.php';

Теперь давайте запустим test.php, перейдя по адресу в браузере: http://myproject.loc/test.php

И увидим, что текст вывелся только однажды.
Только одно подключение файла

Теперь давайте заменим include_once на include:

<?php

include __DIR__ . '/config.php';
include __DIR__ . '/config.php';
include __DIR__ . '/config.php';

А вот теперь код подключился несколько раз:
Несколько подключений

Вот такие пирожки. Чуть позже мы ещё вернёмся к теме этих отличий, и когда именно стоит использовать include_once и require_once.

А пока что на этом всё. Делайте домашнее задание и до встречи на следующих уроках!

loader
loader
30.07.2023 в 07:54
55005
+3583
Домашнее задание
  • Самостоятельно создайте архитектуру, описанную в статье: сделайте шапку, сайдбар, контент и футер в отдельных файлах.
  • Сделайте минимум 4 переменные для каждого из этих блоков в файле index.php и выведете их внутри этих файлов.
  • Изучите официальную документацию по include и изучите как можно использовать выражения вида
    $var = include 'file.php';
Комментарии
Этот урок набрал набрал достаточно большое количество комментариев и дальнейшее его комментирование отключено. Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку, посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали. Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
Логические задачи с собеседований