Как запустить php файл из php

Обновлено: 05.07.2024

Оба способа (с указыванием опции -f или без) запустят файл my_script.php . Нет ограничений, какой файл запускать, и PHP-скрипты не обязаны иметь расширение .php.

Замечание:

Если необходимо передать аргументы в скрипт, то при использовании опции -f первым аргументом должен быть -- .

Передать PHP-код напрямую в командной строке.

Необходимо быть особо осторожным при использовании этого способа, так как может произойти подстановка переменных оболочки при использовании двойных кавычек.

Замечание:

Внимательно прочтите пример: в нем нет открывающих и закрывающих тегов! Опция -r просто в них не нуждается. Их использование приведет к ошибке парсера.

Передать запускаемый PHP-код через стандартный поток ввода (stdin).

Это дает мощную возможность создавать PHP-код и скармливать его запускаемому файлу, как показано в этом (вымышленном) примере:

Как и любое другое консольное приложение, бинарный файл PHP принимает аргументы, но PHP-скрипт также может получать аргументы. PHP не ограничивает количество аргументов, передаваемых в скрипт (оболочка консоли устанавливает некоторый порог количества символов, которые могут быть переданы; обычно этого лимита хватает). Переданные аргументы доступны в глобальном массиве $argv . Первый индекс (ноль) всегда содержит имя вызываемого скрипта из командной строки. Учтите, что если код вызывается на лету из командной строки с помощью опции -r , значением $argv[0] будет просто дефис (-). То же самое верно и для кода, переданного через конвейер из STDIN.

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

Подразумевая что этот файл называется test и находится в текущей директории, можно сделать следующее:

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

if ( $argc != 2 || in_array ( $argv [ 1 ], array( '--help' , '-help' , '-h' , '-?' ))) ?>

Это консольный PHP-скрипт, принимающий один аргумент.

Использование:
<?php echo $argv [ 0 ]; ?> <option>

<option> Любое слово, которое вы хотели бы
напечатать. Опции --help, -help, -h,
или -? покажут текущую справочную информацию.

Для запуска приведенного примера в Unix-системе, необходимо сделать его исполняемым и просто выполнить в консоли script.php echothis или script.php -h. В Windows-системе можно создать пакетный файл:

Также можно ознакомиться с расширением Readline, которое можно использовать для усовершенствования консольного PHP-скрипта.


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

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

Вы спросите: «Ну и что с того? Разве плохо писать всю логику в одном файле?». Стопроцентного ответа на этот вопрос нет, но мой опыт говорит, что код приложения, написанный в одном файле:

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

Если этих доводов недостаточно – советую почитать книгу Роберта Мартина «Чистый код». А пока продолжу.

Представим, что у нас есть 2 файла: `index.php` и `1.php`, лежащих в одной директории.


Задача: вывести содержимое файла "1.php" в контейнере `body`, при запуске файла "index.php". Решить её можно разными способами, и в этом посте мы рассмотрим некоторые из них. Подключение PHP возможно с помощью разных инструкций:

  • `include`
  • `include_once`
  • `require`
  • `require_once`

Самый простой пример решения с `include`:

Результат запуска в браузере:


Как подключить PHP из другой директории

Теперь изменим условия. Переместим файл `1.php` в папку с названием `test`, которую создадим в директории с файлом `index.php`.


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

Далее изменим код в `index.php`.

Строка, что мы указываем после инструкции `include`, это путь к файлу. Он может быть относительный (к файлу, где используется подключение) и абсолютным (от корня файловой системы). В приложениях рекомендуются использовать относительные пути.

Между папками, файлами и другими папками в пути устанавливаются разделители. Универсальный разделитель для различных операционных систем – `/`.

Если в папке `test` у нас была бы еще папка `lot`, в которой лежал файл `1.php`, то относительный путь выглядел бы так: 'test/lot/1.php'.

С путями немного разобрались – возвращаемся к инструкциям. Произведем изменения в файлах. Файл "index.php":

Посмотрим на изменение в выводе:


Как работает подключение кода PHP

Интерпретатор php «читает» код сверху вниз и слева направо, как мы читаем книги на русском языке. На исполнение от сервера ему указывается файл "index.php", а значит, чтение начинается с него. Дойдя до строчки с `include 'test/1.php'`, интерпретатор пытается найти и исполнить это файл так, как будто он является частью "index.php".

Перед подключением и исполнением файла "1.php" уже существует переменная `$say`, в которой содержится 'Hello world!'. При выполнении файла "1.php", содержимое этой переменной выводится на экран и создается переменная `$test`, которая в свою очередь и выводится на экран в файле `index.php`.

Если описанное выше непонятно, советую немного поиграться с файлами `1.php` и `index.php` создавая и выводя в них переменные.

Различия `include`, `include_once`, `require`, `require_once`

Переименуем файл "1.php"в файл "2.php" и обратимся к "index.php":


В итоге получаем ошибку. Но обратите внимание на то, что после вывода ошибки код PHP все равно продолжил выполнение и вывел `End`. Заменим `include` на `require` и запустим на выполнение.


В итоге видим похожие ошибки, но не видим вывода `End` в конце: после ошибки код php прекратил свою работу.

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

Теперь рассмотрим отличие инструкций `require` и `require_once`. Внесем небольшие правки в наши файлы. Вот новый "index.php":


Как видно на скриншоте, с помощью `require` мы успешно подключили файл несколько раз. Снова внесем изменение в файлы. Новый файл "index.php":

И новый файл "2.php" — на этот раз объявим там функцию:


Второе подключение файла "2.php" приводит к ошибке, как раз потому что в этом файле происходит объявление функции. А в PHP-скрипте двух одинаковых функций быть не должно.

Теперь заменим все `require` на `require_once` и запустим снова:


Ура, работает! Но обратим внимание на то, что файл подключился только один раз.

Теперь вновь переименуем файл `2.php` в `1.php` и запустим "index.php".


`Require_once`, так же как и `require` завершает выполнение скрипта, если не найден файл указанный для подключения. Заменим `require_once` на `include_once`:


Ошибок стало больше, но код по-прежнему отработал до конца: end в конце картинки это подтверждает. Внесем правки в "index.php":


Подведём итоги

Чтобы подключить PHP-файлы, можно воспользоваться четырьмя похожими инструкциями — `include` и `include_once`, `require` и `require_once`.

  • Разница между `include` и `require`: при отсутствии файла последняя выводит фатальную ошибку, а первая — нет.
  • Разница между `include` и `include_once` (а также `require` и `require_once` соответственно): инструкции с “once” проверяют перед подключением, был ли этот файл подключен ранее. Если он подключался, повторного подключения не произойдет.
  • Разница между `require_once` и `include_once`: думаю, она понятна из двух предыдущих пунктов :)

Если вы хотите освоить PHP во всей его полноте — приглашаем вас на курсы PHP-разработки в GeekBrains. За шесть месяцев вы изучите не только работу с PHP, но и другие важные в профессии технологии — фреймворк Laravel, базы данных MS SQL и Postgre SQL, основы HTML/CSS и ООП. А также сможете пройти полноценную онлайн-стажировку!

image

PHP это скриптовый язык, созданный изначально для быстрого ваяния домашних страничек (да, да изначально это же был Personal Home Page Tools), а в дальнейшем на нём уже стали создавать магазины, социалки и другие поделки на коленке которые выходят за рамки задуманного, но к чему это я – а к тому, что чем больше функционала закодировано, тем больше желание его правильно структурировать, избавиться от дублирования кода, разбить на логические кусочки и подключать лишь при необходимости (это тоже самое чувство, которое возникло у вас, когда вы читали это предложение, его можно было бы разбить на отдельные кусочки). Для этой цели в PHP есть несколько функции, общий смысл которых сводится к подключению и интерпретации указанного файла. Давайте рассмотрим на примере подключения файлов:


Если запустить скрипт index.php, то PHP всё это будет последовательно подключать и выполнять:


Когда файл подключается, то его код оказывается в той же области видимости, что и строка в которой его подключили, таким образом все переменные, доступные в данной строке будут доступны и в подключаемом файле. Если в подключаемом файле были объявлены классы или функции, то они попадают в глобальную область видимости (если конечно для них не был указан namespace).

Если вы подключаете файл внутри функции, то подключаемые файлы получают доступ к области видимости функции, таким образом следующий код тоже будет работать:

Отдельно отмечу магические константы: __DIR__ , __FILE__ , __LINE__ и прочие — они привязаны к контексту и выполняются до того, как происходит включение

Особенностью подключения файлов является тот момент, что при подключении файла парсинг переключается в режим HTML, по этой причине любой код внутри включаемого файла должен быть заключен в PHP теги:


Если у вас в файле только PHP код, то закрывающий тег принято опускать, дабы случайно не забыть какие-нить символы после закрывающего тега, что чревато проблемами (об этом я ещё расскажу в следующей статье).

А вы видели сайт-файл на 10 000 строк? Аж слёзы на глазах (╥_╥)…

Функции подключения файлов

Как уже было сказано выше, в PHP существует несколько функций для подключения файлов:

    — включает и выполняет указанный файл, если не находит — выдаёт предупреждение E_WARNING — аналогично функции выше, но включает файл единожды — включает и выполняет указанный файл, если не находит — выдаёт фатальную ошибку E_ERROR — аналогично функции выше, но включает файл единожды
В действительности, это не совсем функции, это специальные языковые конструкции, и можно круглые скобочки не использовать. Кроме всего прочего есть и другие способы подключения и выполнения файлов, но это уже сами копайте, пусть это будет для вас «задание со звёздочкой» ;)

Давайте разберём на примерах различия между require и require_once , возьмём один файл echo.php:


И будем его подключать несколько раз:


Результатом выполнения будет два подключения файла echo.php:


Существует ещё парочка директив, которые влияют на подключение, но они вам не потребуются — auto_prepend_file и auto_append_file. Эти директивы позволяют установить файлы которые будут подключены до подключения всех файлов и после выполнения всех скриптов соответственно. Я даже не могу придумать «живой» сценарий, когда это может потребоваться.

Где ищет?

PHP ищет подключаемые файлы в директориях прописанных в директиве include_path. Эта директива также влияет на работу функций fopen() , file() , readfile() и file_get_contents() . Алгоритм работы достаточно простой — при поиске файлов PHP по очереди проверяет каждую директорию из include_path , пока не найдет подключаемый файл, если не найдёт — вернёт ошибку. Для изменения include_path из скрипта следует использовать функцию set_include_path().

При настройке include_path следует учитывать один важный момент — в качестве разделителя путей в Windows и Linux используются различные символы — ";" и ":" соответственно, так что при указании своей директории используйте константу PATH_SEPARATOR , например:


Когда вы прописываете include_path в ini файле, то можете использовать переменные окружения типа $ :

Если при подключении файла вы прописываете абсолютный путь (начинающийся с "/") или относительный (начинающийся с "." или ".."), то директива include_path будет проигнорирована, а поиск будет осуществлён только по указанному пути.

Возможно стоило бы рассказать и про safe_mode, но это уже давно история (с версии 5.4), и я надеюсь вы сталкиваться с ним не будете, но если вдруг, то чтобы знали, что такое было, но прошло.

Использование return

Расскажу о небольшом life-hack'е — если подключаемый файл возвращает что-либо с использованием конструкции return , то эти данные можно получить и использовать, таким образом можно легко организовать подключение файлов конфигурации, приведу пример для наглядности:

Занимательные факты, без которых жилось и так хорошо: если во включаемом файле определены функции, то они могут быть использованы в основном файле вне зависимости от того, были ли они объявлены до return или после

Написать код, который будет собирать конфигурацию из нескольких папок и файлов. Структура файлов следующая:


При этом код должен работать следующим образом:

  • если в системном окружении есть переменная PROJECT_PHP_SERVER и она равна development , то должны быть подключены все файлы из папки default, данные занесены в перемененную $config , затем подключены файлы из папки development, а полученные данные должны перетереть соответствующие пункты сохраненные в $config
  • аналогичное поведение если PROJECT_PHP_SERVER равна production (естественно только для папки production)
  • если переменной нет, или она задана неверно, то подключаются только файлы из папки default

Автоматическое подключение

Конструкции с подключением файлов выглядят очень громоздко, так и ещё и следить за их обновлением — ещё тот подарочек, зацените кусочек кода из примера статьи про исключения:


Первой попыткой избежать подобного «счастья» было появление функции __autoload. Сказать точнее, это была даже не определенная функция, эту функцию вы должны были определить сами, и уже с её помощью нужно было подключать необходимые нам файлы по имени класса. Единственным правилом считалось, что для каждого класса должен быть создан отдельный файл по имени класса (т.е. myClass должен быть внутри файла myClass.php). Вот пример реализации такой функции __autoload() (взят из комментариев к официальному руководству):

Класс который будем подключать:


Файл, который подключает данный класс:


Теперь о проблемах с данной функцией — представьте ситуацию, что вы подключаете сторонний код, а там уже кто-то прописал функцию __autoload() для своего кода, и вуаля:


Чтобы такого не было, создали функцию, которая позволяет регистрировать произвольную функцию или метод в качестве загрузчика классов — spl_autoload_register. Т.е. мы можем создать несколько функций с произвольным именем для загрузки классов, и зарегистрировать их с помощью spl_autoload_register . Теперь index.php будет выглядеть следующим образом:

Рубрика «а вы знали?»: первый параметр spl_autoload_register() не является обязательным, и вызвав функцию без него, в качестве загрузчика будет использоваться функция spl_autoload, поиск будет осуществлён по папкам из include_path и файлам с расширением .php и .inc , но этот список можно расширить с помощью функции spl_autoload_extensions
Теперь каждый разработчик может регистрировать свой загрузчик, главное чтобы имена классов не совпадали, но это не должно стать проблемой, если вы используете пространства имён.
Поскольку уже давно существует такой продвинутый функционал как spl_autoload_register() , то функцию __autoload() уже заявлена как deprecated в PHP 7.1, а это значит, что в обозримом будущем данную функцию и вовсе уберут (Х_х)
  1. Каждая библиотека должна жить в собственном пространстве имён (т.н. vendor namespace)
  2. Для каждого пространства имён должна быть создана собственная папка
  3. Внутри пространства имён могут быть свои подпространства — тоже в отдельных папках
  4. Один класс — один файл
  5. Имя файла с расширением .php должно точно соответствовать имени класса
Полное имя класса Пространство имён Базовая директория Полный путь
\Acme\Log\Writer\File_Writer Acme\Log\Writer ./acme-log-writer/lib/ ./acme-log-writer/lib/File_Writer.php
\Aura\Web\Response\Status Aura\Web /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php
\Symfony\Core\Request Symfony\Core ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php
\Zend\Acl Zend /usr/includes/Zend/ /usr/includes/Zend/Acl.php

Различия этих двух стандартов, лишь в том, что PSR-0 поддерживает старый код без пространства имён (т.е. до версии 5.3.0), а PSR-4 избавлен от этого анахронизма, да ещё и позволяет избежать ненужной вложенности папок.

Благодаря этим стандартам, стало возможно появление такого инструмента как composer — универсального менеджера пакетов для PHP. Если кто пропустил, то есть хороший доклад от pronskiy про данный инструмент.

PHP-инъекция

Ещё хотел рассказать о первой ошибки всех, кто делает единую точку входа для сайта в одном index.php и называет это MVC-фреймворком:


Смотришь на код, и так и хочется чего-нить вредоносного туда передать:


Первое, что приходит на ум — принудительно добавлять расширение .php , но в ряде случаев это можно обойти «благодаря» уязвимости нулевого байта (почитайте, эту уязвимость уже давно исправили, но вдруг вам попадётся интерпретатор более древний, чем PHP 5.3, ну и для общего развития тоже рекомендую):

В современных версиях PHP наличие символа нулевого байта в пути подключаемого файла сразу приводит к соответствующей ошибке подключения, и даже если указанный файл существует и его можно подключить, то в результате всегда будет ошибка, проверяется это следующим образом strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename) (это из недров самого PHP)

Вторая «стоящая» мысль, это проверка на нахождение файла в текущей директории:


Третья, но не последняя модификация проверки, это использование директивы open_basedir, с её помощью можно указать директорию, где именно PHP будет искать файлы для подключения:

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

Какие ещё возможны проверки? Уйма вариантов, всё зависит от архитектуры вашего приложения.

Хотел ещё вспомнить о существовании «чудесной» директивы allow_url_include (у неё зависимость от allow_url_fopen), она позволяет подключать и выполнять удаленный PHP файлы, что куда как опасней для вашего сервера:


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

Написать скрипт, который позволит подключать php-скрипты из текущей папки по названию, при этом следуют помнить о возможных уязвимостях и не допустить промашек.

В заключение

Данная статья — основа-основ в PHP, так что изучайте внимательно, выполняйте задания и не филоньте, за вас никто учить не будет.

loader

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

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

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

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

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

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

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

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

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

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

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

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

Работа директивы include

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

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

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

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

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

Однако между ними всё же есть разница. Она заключается в том, что если подключаемый файл не найден, то при 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. У меня получился вот такой код:

Свёрстанная страничка

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

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

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

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

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

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

Динамически сформированная страничка

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

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

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

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

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

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

Только одно подключение файла

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

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

Несколько подключений

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

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

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

Читайте также: