PHP: Модули
Пока программа маленькая, весь код можно хранить в одном файле. Такой подход удобен для простых примеров и небольших задач. Но со временем программа начинает расти. Когда кода становится много, ориентироваться в одном файле становится сложно. Между тем реальные приложения состоят из десятков тысяч строк (как минимум) и сотен файлов.
Чтобы разделить программу на отдельные логические части, код раскладывают по файлам. Во многих языках такие файлы называются модулями. В PHP модуль — это обычный файл с кодом и расширением .php. А язык предоставляет механизм для обращения к функциям и константам из других файлов — подключение файлов.
Как подключить файл
Инструкция require подключает указанный файл и делает его содержимое доступным:
<?php
// helpers.php
function sayHi(): void
{
print_r('Hi!');
}<?php
// Solution.php
require 'helpers.php';
sayHi(); // => Hi!После подключения все функции из файла helpers.php доступны так, как будто они были определены прямо в текущем файле.
Кстати, вы уже видели этот механизм в действии. Автоматизированные тесты в этом курсе подключают файл с вашим решением строкой require 'Solution.php'; — и после этого могут вызывать функции, которые вы определили.
require, include и require_once
У require есть близнец — инструкция include. Разница проявляется, когда подключаемый файл не найден: include выведет предупреждение, и программа продолжит работу, а require остановит выполнение с ошибкой. Если без подключаемого кода программа не имеет смысла, используют require.
Есть и третий вариант — require_once. Он подключает файл только один раз, даже если инструкция встречается в программе многократно. Это важно для файлов с функциями: повторное определение функции с тем же именем приводит к ошибке.
Встроенные функции доступны без подключения
Стандартная библиотека PHP устроена проще, чем во многих других языках: встроенные функции доступны в любом месте программы сразу, без какого-либо подключения. Например, функции округления: floor() округляет число вниз до ближайшего целого, ceil() округляет вверх:
<?php
print_r(floor(7.9)); // => 7
print_r(ceil(7.1)); // => 8
print_r(ceil(7.0)); // => 7Разница заметна, когда число не целое. floor(7.9) дает 7, а не 8, потому что 7 — ближайшее целое снизу.
Встроенные функции, конечно, доступны и в теле своих функций:
<?php
// Вычисляет количество поездок, необходимых для перевозки всех предметов
function tripsNeeded(int $items, int $capacity): int
{
return (int) ceil($items / $capacity);
}
print_r(tripsNeeded(10, 3)); // => 4Обратите внимание: ceil() возвращает число типа float, поэтому результат приводится к int — так, как мы делали в уроке про преобразование типов.
Конфликты имен
В больших программах разные части кода могут содержать функции с одинаковыми названиями. В PHP нельзя определить две функции с одним именем в одном пространстве — программа завершится с ошибкой Cannot redeclare function.
Для борьбы с конфликтами имен в PHP существуют пространства имен (namespaces). Вы видели их в начале каждого задания этого курса — строка namespace HexletBasics\...; как раз объявляет пространство имен. Благодаря им мы можем создавать сколько угодно функций с одинаковыми именами, главное чтобы они находились в разных пространствах. Это работает даже со встроенными функциями:
<?php
namespace App\Custom;
function floor(float $number): string
{
return 'custom floor';
}
print_r(floor(3.7)); // => custom floor
print_r(\floor(3.7)); // => 3Внутри пространства App\Custom имя floor ссылается на нашу функцию. Встроенная функция при этом никуда не делась — она доступна по полному имени \floor(), где обратный слеш означает глобальное пространство. Это особенно важно при использовании сторонних библиотек, потому что разные разработчики могут выбирать одинаковые имена для функций. Подробно пространства имен изучаются дальше, на Хекслете.
Задание
Реализуйте функцию amountPerPerson(). Она принимает сумму счета в ресторане, количество человек и процент чаевых, а возвращает сумму, которую платит каждый. Итог округляется вверх — никто не должен недоплачивать.
Для округления используйте встроенную функцию ceil(). Она доступна сразу — подключать ничего не нужно.
<?php
// Счет 300, 4 человека, чаевые 20% — итого 360, каждый платит 90
print_r(amountPerPerson(300, 4, 20)); // => 90
// Счет 350, 3 человека, чаевые 10% — итого 385, каждый платит 129
print_r(amountPerPerson(350, 3, 10)); // => 129Подсказка
- Сначала посчитайте итоговую сумму с чаевыми, затем разделите на количество человек и округлите вверх
ceil()возвращает число типаfloat, а функция должна вернутьint— пригодится приведение типов
Полезное
PHP: Модули
Пока программа маленькая, весь код можно хранить в одном файле. Такой подход удобен для простых примеров и небольших задач. Но со временем программа начинает расти. Когда кода становится много, ориентироваться в одном файле становится сложно. Между тем реальные приложения состоят из десятков тысяч строк (как минимум) и сотен файлов.
Чтобы разделить программу на отдельные логические части, код раскладывают по файлам. Во многих языках такие файлы называются модулями. В PHP модуль — это обычный файл с кодом и расширением .php. А язык предоставляет механизм для обращения к функциям и константам из других файлов — подключение файлов.
Как подключить файл
Инструкция require подключает указанный файл и делает его содержимое доступным:
<?php
// helpers.php
function sayHi(): void
{
print_r('Hi!');
}<?php
// Solution.php
require 'helpers.php';
sayHi(); // => Hi!После подключения все функции из файла helpers.php доступны так, как будто они были определены прямо в текущем файле.
Кстати, вы уже видели этот механизм в действии. Автоматизированные тесты в этом курсе подключают файл с вашим решением строкой require 'Solution.php'; — и после этого могут вызывать функции, которые вы определили.
require, include и require_once
У require есть близнец — инструкция include. Разница проявляется, когда подключаемый файл не найден: include выведет предупреждение, и программа продолжит работу, а require остановит выполнение с ошибкой. Если без подключаемого кода программа не имеет смысла, используют require.
Есть и третий вариант — require_once. Он подключает файл только один раз, даже если инструкция встречается в программе многократно. Это важно для файлов с функциями: повторное определение функции с тем же именем приводит к ошибке.
Встроенные функции доступны без подключения
Стандартная библиотека PHP устроена проще, чем во многих других языках: встроенные функции доступны в любом месте программы сразу, без какого-либо подключения. Например, функции округления: floor() округляет число вниз до ближайшего целого, ceil() округляет вверх:
<?php
print_r(floor(7.9)); // => 7
print_r(ceil(7.1)); // => 8
print_r(ceil(7.0)); // => 7Разница заметна, когда число не целое. floor(7.9) дает 7, а не 8, потому что 7 — ближайшее целое снизу.
Встроенные функции, конечно, доступны и в теле своих функций:
<?php
// Вычисляет количество поездок, необходимых для перевозки всех предметов
function tripsNeeded(int $items, int $capacity): int
{
return (int) ceil($items / $capacity);
}
print_r(tripsNeeded(10, 3)); // => 4Обратите внимание: ceil() возвращает число типа float, поэтому результат приводится к int — так, как мы делали в уроке про преобразование типов.
Конфликты имен
В больших программах разные части кода могут содержать функции с одинаковыми названиями. В PHP нельзя определить две функции с одним именем в одном пространстве — программа завершится с ошибкой Cannot redeclare function.
Для борьбы с конфликтами имен в PHP существуют пространства имен (namespaces). Вы видели их в начале каждого задания этого курса — строка namespace HexletBasics\...; как раз объявляет пространство имен. Благодаря им мы можем создавать сколько угодно функций с одинаковыми именами, главное чтобы они находились в разных пространствах. Это работает даже со встроенными функциями:
<?php
namespace App\Custom;
function floor(float $number): string
{
return 'custom floor';
}
print_r(floor(3.7)); // => custom floor
print_r(\floor(3.7)); // => 3Внутри пространства App\Custom имя floor ссылается на нашу функцию. Встроенная функция при этом никуда не делась — она доступна по полному имени \floor(), где обратный слеш означает глобальное пространство. Это особенно важно при использовании сторонних библиотек, потому что разные разработчики могут выбирать одинаковые имена для функций. Подробно пространства имен изучаются дальше, на Хекслете.
Задание
Реализуйте функцию amountPerPerson(). Она принимает сумму счета в ресторане, количество человек и процент чаевых, а возвращает сумму, которую платит каждый. Итог округляется вверх — никто не должен недоплачивать.
Для округления используйте встроенную функцию ceil(). Она доступна сразу — подключать ничего не нужно.
<?php
// Счет 300, 4 человека, чаевые 20% — итого 360, каждый платит 90
print_r(amountPerPerson(300, 4, 20)); // => 90
// Счет 350, 3 человека, чаевые 10% — итого 385, каждый платит 129
print_r(amountPerPerson(350, 3, 10)); // => 129Подсказка
- Сначала посчитайте итоговую сумму с чаевыми, затем разделите на количество человек и округлите вверх
ceil()возвращает число типаfloat, а функция должна вернутьint— пригодится приведение типов
Полезное
Ваше упражнение проверяется по этим тестам
<?php
namespace HexletBasics\DefineFunctions\Modules;
use HexletBasics\Exercise\TestCase;
class SolutionTest extends TestCase
{
public function test()
{
$this->assertEquals(75, amountPerPerson(300, 4, 0));
$this->assertEquals(90, amountPerPerson(300, 4, 20));
$this->assertEquals(129, amountPerPerson(350, 3, 10));
$this->assertEquals(34, amountPerPerson(100, 3, 0));
}
}Решение учителя откроется через:
20:00
