Это требуется для того, чтобы переменная всегда указывала на нужный объект.
Я лучше приведу пример с объектами, вместо передачи в функцию. Думаю, так будет чуть нагляднее.
Например есть некоторый "писатель в логи":
class Writer
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function write(): void
{
$this->logger->warning('Hello');
}
}
Его использование довольно тривиально:
$logger = new StreamLogger('php://stdout');
$writer = new Writer($logger);
$writer->write(); // "Hello"
В этом случае, если изменить логгер, то наш "писатель" сохранит внутри старый объект.
$logger = new StreamLogger('php://stdout');
$writer = new Writer($logger);
$writer->write(); // "Hello"
$logger = new NullLogger();
$some->write(); // "Hello"
Т.е. внутри Writer хранится
старый объект StreamLogger, вместо нового NullLogger.
А если передать объект по ссылке, то он всегда будет хранить своё состояние.
// Изменяем на передачу по ссылке
public function __construct(LoggerInterface &$logger)
{
$this->logger = &$logger;
}
$logger = new StreamLogger('php://stdout');
$writer = new Writer($logger);
$writer->write(); // "Hello"
$logger = new NullLogger();
$some->write(); // ничего
Этот функционал требуется для обеспечения консистентности приложения, если очень часто используется делегирование и предполагается замена или переконфигурирование частей системы "на лету". Такая задача может возникнуть, например, при разработке приложений, которые постоянно висят в памяти (например: веб-сокет сервера ну или сайты, работающие из под roadrunner, swoole, etc.).
Прим.: В качестве альтернативы передачи по ссылке можно воспользоваться всякими паттернами, вроде обсервера, которые должны передавать события об изменении переменной. Иногда это лучше, иногда наоборот, оверинжинеринг.