Кроссплатформенная разработка на PHP: пишем код, который работает везде

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему «работает на моей машине» — это приговор?

Привет, коллега! Если ты когда-нибудь слышал фразу «У меня всё работает, а на сервере — нет», и при этом нервно смеялся, — эта статья для тебя. Кроссплатформенная разработка на PHP — это не просто модный термин, а навык выживания в современной веб-разработке. Мы живем в мире, где локально у тебя может стоять macOS или Windows, а продакшн крутится на Linux. И если твой код не умеет дружить с разными операционными системами, ты обречен на вечные баги и бессонные ночи.

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

Главные враги кроссплатформенности в PHP

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

1. Разделители директорий: / против \

Классика жанра. Windows использует обратную косую черту (\), а Linux и macOS — прямую (/). Если ты хардкодишь пути, ты проиграл.

<?php
// ПЛОХО: сломается на Linux
$path = 'C:\projects\myapp\logs\app.log';

// ХОРОШО: используем DIRECTORY_SEPARATOR
$path = 'projects' . DIRECTORY_SEPARATOR . 'myapp' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . 'app.log';

// ЕЩЕ ЛУЧШЕ: используем / — работает везде
$path = 'projects/myapp/logs/app.log';
?>

Совет: даже внутри PHP многие функции (например, fopen()) корректно обрабатывают прямую косую черту на Windows. Поэтому старайся использовать именно / — это самый простой способ сделать кроссплатформенную разработку на PHP без головной боли.

2. Символы конца строки (EOL)

Windows использует \r\n, Linux — \n, а старая добрая macOS (до версии X) — \r. Если ты пишешь скрипты для обработки текстовых файлов или логов, это станет проблемой.

<?php
// Универсальный способ разбить текст на строки
$text = file_get_contents('data.txt');
$lines = preg_split('/\r\n|\r|\n/', $text);

// Или используем встроенную константу PHP_EOL для вывода
echo "Первая строка" . PHP_EOL . "Вторая строка";
?>

Константа PHP_EOL автоматически подставляет правильный символ для той ОС, на которой выполняется скрипт. Это идеальный вариант, когда ты пишешь логи или генерируешь текстовые файлы.

3. Регистр файлов и путей

На Windows файловая система не чувствительна к регистру (File.txt и file.txt — одно и то же). На Linux — чувствительна. Если ты подключаешь файлы с неправильным регистром, на продакшене получишь 500 ошибку.

<?php
// ПЛОХО: может не сработать на Linux
require_once 'Includes/Config.PHP';

// ХОРОШО: всегда соблюдаем регистр
require_once 'includes/config.php';
?>

Лучшая практика — договориться в команде о едином стиле именования файлов (например, snake_case.php или camelCase.php) и всегда использовать точное совпадение регистра. Автозагрузка Composer с PSR-4 стандартами тоже решает эту проблему, но только если ты следуешь неймспейсам.

Работа с путями: используем современные инструменты

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

Волшебная функция realpath()

realpath() преобразует любой относительный путь в абсолютный, используя правильные разделители для текущей ОС.

<?php
$relativePath = '../logs/error.log';
$absolutePath = realpath($relativePath);
echo $absolutePath; // Например: /var/www/project/logs/error.log
?>

Сборка путей через DIRECTORY_SEPARATOR

Если тебе нужно динамически собрать путь, используй константу DIRECTORY_SEPARATOR.

<?php
function buildPath(...$segments) {
    return implode(DIRECTORY_SEPARATOR, $segments);
}

$path = buildPath(__DIR__, 'storage', 'logs', 'app.log');
echo $path; // Правильный путь для любой ОС
?>

Библиотека Symfony Filesystem

Для сложных проектов рекомендую подключить symfony/filesystem. Она решает все проблемы с путями, правами доступа и копированием файлов.

<?php
require_once 'vendor/autoload.php';

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;

$fs = new Filesystem();
try {
    $fs->mkdir('/tmp/'.uniqid());
    $fs->copy('source.txt', 'destination.txt', true);
} catch (IOExceptionInterface $exception) {
    echo "Ошибка: " . $exception->getMessage();
}
?>

Кодировки и локали: еще один камень преткновения

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

<?php
// Всегда устанавливай UTF-8 в начале скрипта
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');

// Для работы с файлами используй iconv или mb_convert_encoding
$content = file_get_contents('data.txt');
$content = mb_convert_encoding($content, 'UTF-8', 'auto');
?>

Также обращай внимание на функции strtoupper() и strtolower() — они не работают с мультибайтовыми кодировками. Используй mb_strtoupper() и mb_strtolower().

Docker: идеальное решение для кроссплатформенной разработки

Если ты хочешь раз и навсегда забыть о проблемах «у меня работает, а у тебя нет», используй Docker. Контейнеризация позволяет запускать одно и то же окружение на любой ОС.

Пример простого docker-compose.yml для PHP-проекта:

version: '3.8'
services:
  php:
    image: php:8.2-cli
    volumes:
      - .:/var/www/html
    working_dir: /var/www/html
    command: php -S 0.0.0.0:8000
  nginx:
    image: nginx:latest                

Блоги

Рекомендаций по книгам