Пути к файлам - тема, которая обычно взрывает мозг новичкам. Но не волнуйся, сейчас мы всё расставим по полочкам.
Чем отличаются пути в PHP и URL
Когда мы смотрим любимый фильм или сериал, мы видим только готовый продукт.
А за кадром существует совсем другой, невидимый для нас мир: стилисты и гримёры, искусственные декорации, наложение спецэффектов и многое другое.
В PHP существует такое же разделение. С одной стороны - реальная файловая система с реальными папками и файлами, с другой - URL адреса, которые могут не иметь ничего общего с реальной файловой структурой.
Если ты видишь на каком-нибудь сайте страницу с URL /category/monitors - это совсем не значит, что на сайте есть скрипт /category/monitors/index.php.
Вполне вероятно, что и такой папки там тоже нет, а все URL адреса обрабатываются одним единственным PHP файлом.
И даже если в URL присутствует расширение файла, например /about.html - это тоже не говорит о существовании файла about.html. Может он есть, а может и нет.
Новички часто путают пути к реальным файлам с URL адресами. Сейчас я разберу пару таких ошибок, на примере которых можно будет прочувствовать разницу.
Ошибка №1: Подстановка физического пути в URL
Очень частая ошибка новичков - пытаться подставить в URL адрес ссылку на физический файл, вроде такого:
<a href="D:\OpenServer\domains\test.ru\article.php">Статья</a>
Это неправильно. Браузер не может видеть реальную файловую структуру сервера. Он не видит никаких дисков D, он видит только URL адреса.
Правильная ссылка выглядит так (разницу объясню чуть позже):
<a href="http://test.ru/article.php">Статья</a>
<a href="/article.php">Статья</a>
<a href="article.php">Статья</a>
Ошибка №2: Подключение скриптов по URL
Иногда новички пытаются подключить физический файл по его URL:
require 'http://test.ru/article.php';
Это неправильно. Во-первых, подключится не сам скрипт, а результат его работы. Во-вторых, подключать какие-то файлы через URL вообще идея очень опасная.
Как правильно:
require 'config.php';
require 'D:\OpenServer\domains\test.ru\config.php';
require __DIR__ . '/config.php';
Абсолютный путь в PHP
Абсолютный путь - это полный путь к папке или файлу. Вот пара примеров для разных операционных систем:
- D:\OpenServer\domains\test.ru\index.php - для OpenServer на Windows
- /var/www/html/test.ru/index.php - для Ubuntu
Как видите, это полный путь от корня диска до конкретного файла или папки. Начинается со слеша или буквы диска (Windows).
Получить абсолютный путь скрипта можно с помощью магической константы __FILE__:
<?php
echo __FILE__;
Для получения абсолютного пути к папке, в которой находится скрипт, есть магическая константа __DIR__:
<?php
echo __DIR__;
Как этим пользоваться. Допустим, у нас в корне сайта лежат файлы index.php и config.php и мы хотим подключить второй в первый.
Если мы хотим подключить config.php по его абсолютному пути, есть два способа сделать это:
<?php
# Указать путь вручную
require 'D:\OpenServer\domains\test.ru\cpnfig.php';
# Подставить путь к текущей папке и добавить имя файла вручную
require __DIR__ . '/config.php';
Поскольку константа __DIR__ не добавляет слеш после последней папки, мы указываем его вручную.
Относительный путь в PHP
У относительных путей в PHP есть один подвох - они могут строиться относительно не той папки, от которой мы ожидаем.
Дело в том, что когда мы подключаем скрипт по относительному пути require('config.php');, PHP будет искать его по следующему алгоритму:
Сначала PHP попытается найти этот файл в папках, указанных в директиве include_path. Посмотреть, что указано в этой директиве конкретно у вас можно с помощью var_dump(get_include_path());, папки разделяются символом ;
Если мы укажем путь к скрипту в таком виде: require('./config.php');, то этот шаг будет пропущен.
- Затем PHP попытается найти файл в папке, в которой находится подключающий скрипт (в нашем случае index.php).
Далее PHP попытается найти файл в папке текущего рабочего каталога.
Например, если мы в index.php подключили файл scripts/script.php, а в этом самом script.php уже пытаемся подключить файл по относительному пути, тогда поиск файла произойдёт и в папке scripts тоже.
Два последних пункта - главная проблема относительных путей. Мы не можем быть уверены, что будет подключен именно тот файл, который нам нужен.
Именно по этой причине я призываю тебя отказаться от использования относительных путей в PHP.
Кому-то из практикующих разработчиков эта фраза может не понравиться, но я считаю это единственным разумным решением.
Тем более нет ничего сложного в добавлении константы __DIR__ перед именем скрипта, что автоматически сделает путь абсолютным.
<?php
# Отказываемся
require 'config.php';
# Используем
require __DIR__ . '/config.php';
Абсолютный путь в URL
Абсолютный путь в URL означает путь от корня сайта. Корень сайта - это папка, которая содержит публичную часть сайта, т.е. доступную извне.
По-умолчанию корень сайта - это сама папка с сайтом, например site.ru, но зачастую её меняют на site.ru/public, чтобы часть скриптов нельзя было запустить по прямой ссылке в браузере.
Есть несколько способов указать абсолютный путь в URL:- http://test.ru/article.php - полный путь с протоколом и доменом
- //test.ru/article.php - полный путь без протокола (берётся из текущей страницы). Содержит два слеша в начале.
- /article.php - полный путь без протокола и домена (берутся из текущей страницы). Содержит слеш в начале.
Второй и третий варианты удобны тем, что при миграции с http на https и обратно все ссылки автоматически сменят протокол, не нужно будет бегать по всему сайту и менять вручную.
Лично я практически всегда использую третий вариант, кроме случаев, когда нужно указать ссылку на другой поддомен (blog.site.ru, shop.site.ru и т.д.).
Относительный путь в URL
Относительные пути в URL указываются без слеша в начале ссылки, например:
<a href="articles">Ссылка</a>
Относительные пути в URL более предсказуемы, чем в PHP. Но я рекомендую использовать их только там, где это действительно необходимо.
Чаще всего их использование приводит к путанице. И вот пара типичных проблем, с которыми часто сталкиваются новички.
Ошибка №1: относительные пути к стилям, скриптам и другим файлам
Представим, что мы решили подключить стили к нашему сайту:
<link rel="stylesheet" type="text/css" href="style.css">
Разработчик указывает относительный URL style.css и видит, что всё работает. По крайней мере, на главной странице.
Но при переходе по любой ссылке, например /products/15, стили перестают работать.
А причина в том, что относительный путь строится от текущего URL-адреса, а значит в нашем примере он из style.css превратился в /products/15/style.css.
Ошибка №2: Рекурсия в ссылках
При использовании относительных путей есть риск случайно создать на сайте бесконечные ссылки. Вот один из таких способов:
<a href="articles/about">О нас</a>
Для работы данного кода должна быть настроена единая точка входа.
Проблема в том, что при каждом клике по этой ссылке текущий URL будет не перезаписываться, а дополняться, в итоге через несколько кликов мы получим что-то вроде http://test.ru/articles/articles/articles/articles/about.
Текущий и родительский каталоги
Помимо указания конкретных папок, мы также можем добавить в путь указание "перейти на папку выше", например:
<?php
include '../config.php';
В коде выше мы подключим файл config.php, который находится не в текущей папке, а в родительской. С абсолютными путями это тоже работает:
<?php
include __DIR__ . '/../config.php';
И с URL-адресами тоже:
<a href="../article.php">Статья</a>
Также мы можем указать ссылку на текущий каталог, что бывает актуально в некоторых операционных системах:
<?php
include './config.php';