Вопрос: Попинайте 2. Удалось ли исправить устаревший код, который забраковал работодатель?

Лучший ответ:
Согласен с FanatPHP по поводу того что изменения, по сравнению с предыдущим вариантом, просто колоссальные, поздравляю!

Однако сразу видны те направления движения которые стоит рассматривать в первую очередь:


Вам стоит лучше изучить возможности языка. PHP развивается очень динамично и в 7-й версии было добавлено огромное количество вкусных возможностей, про них стоит знать и ими стоит пользоваться
Необходимо лучше изучить имеющуюся на данный момент экосистему готовых пакетов, это позволит вам использовать готовые, проверенные решения вместо изобретения своих велосипедов. Подключение Twig - первый шаг, но далеко не последний
Вам обязательно стоит посвятить время изучению кода популярных проектов. Это многое может рассказать вам о подходах к решениям, паттернах и т.п. Конечно, параллельно нужно будет выяснять значения массы используемых терминов чтобы лучше понимать происходящее, это тоже пойдёт вам на пользу.
Смотрите как развиваются другие технологии, которые вы используете, таблицами сейчас не верстают :)
Рекомендую рассмотреть вариант использования для написания кода нормальной IDE, к примеру PHPStorm, это существенно улучшит вашу производительность и убережёт от массы ошибок


Теперь более предметно:

Оформление кода:

Вы утверждаете что код соответствует PSR-2 (кстати, актуальный - PSR-12), однако есть мелкие огрехи (раздел 2.2).

Оформление composer.json:

Лучше указывать требования к платформе, в вашем случае - как минимум версию PHP т.к. platform requirements проверяются Composer'ом при установке.

Поскольку ваш проект - не библиотека, то composer.lock тоже должен быть частью репозитория.

Про настройки autoload'а вам уже сказали, обращу только внимание на то что сейчас структура репозитория отражает PSR-0, а не актуальный PSR-4, при использовании PSR-4 ваш код проекта лежал бы в src.

Организация репозитория

Код проекта должен лежать за пределами web root, поэтому вам явно не хватает папки public с единственным index.php

Конфигурация

Конфигурирование через константы - весьма устаревший подход. К примеру представьте что вы разворачиваете этот код на production сервере и вам нужно сменить данные для подключения к базе данных не создавая локальных изменений в рабочей копии. Сейчас у вас это не получится. Выход: читаем про
12 factor app и, в частности, раздел config, а затем подключаем в проект, к примеру, vlucas/phpdotenv или symfony/dotenv

Сервисы

Использование bootstrap.php - хорошо, но для организации работы с сервисами сейчас как правило используются dependency injection контейнеры, даже PSR-11 для них есть. В текущем виде ваш подход слабо расширяем, а передача сервисов через глобальные переменные - так себе идея по многим причинам.

Понятно что вворачивать DI container для примера на три файлика - overkill, но с самим подходом вам следует ознакомиться. Из реализаций самая популярная сейчас - symfony/dependency-injection, но есть и альтернативы.

Автолоадер

Про autoload.php вам уже сказали, вместо него стоит корректно конфигурировать автозагрузку в composer.json и полагаться на то что Composer вам сгенерирует. Он ведь умеет всё это и оптимизировать при необходимости.

Внешние пакеты

Для новых проектов рекомендуется выбирать актуальные и поддерживаемые версии пакетов. Хотя Twig 1.x ещё поддерживается, тем не менее актуальная версия - 3.x.

Обработка ошибок

Попробовать сделать это самостоятельно, безусловно, полезно чтобы лучше разобраться как это работает, но для реальной работы лучше полагаться на проверенные решения, к примеру filp/whoops или symfony/error-handler

Типы данных

Важно помнить что PHP с версии 7.0 поддерживает указание скалярных типов для аргументов и
возвращаемых значений, с 7.1 - nullable типы и class constant visibility, а с 7.4 - типизированные свойства. Всё это гораздо надёжнее чем описание типов через аннотации и этим стоит пользоваться.

Также повсеместно в коде используется нестрогое сравнение, тогда как очень желательно всегда использовать строгое (документация).

Data Objects

Сейчас Place и PlaceFilter по сути являются data объектами т.е. они не содержат самостоятельной логики, а просто переносят некие данные. При этом оба этих класса имеют пустые конструкторы (которые, кстати, лучше убирать), а загрузка данных организована через setter методы. Это позволяет изменить данные в них в произвольные моменты времени что вряд ли является желаемым поведением. Вместо этого подобные объекты лучше организовывать в виде immutable объектов (статья с примерами) чтобы не позволять ненужного нарушения целостности данных. Альтернативно, к примеру, для PlaceFilter может лучше подходить использование паттерна
    Builder, хотя в википедии не самый лучший пример.

Именование

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

Оптимизации

Понятно что это мелочи, но явно видно что компиляцию запросов (1, 2) можно кэшировать вместо того чтобы перекомпилировать каждый раз.

References

PDOStatement::bindParam() принимает аргумент $variable как reference, а в коде в этот аргумент передаётся выражение что недопустимо.

Английский язык

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

Худший ответ:
Согласен с FanatPHP по поводу того что изменения, по сравнению с предыдущим вариантом, просто колоссальные, поздравляю!

Однако сразу видны те направления движения которые стоит рассматривать в первую очередь:


Вам стоит лучше изучить возможности языка. PHP развивается очень динамично и в 7-й версии было добавлено огромное количество вкусных возможностей, про них стоит знать и ими стоит пользоваться
Необходимо лучше изучить имеющуюся на данный момент экосистему готовых пакетов, это позволит вам использовать готовые, проверенные решения вместо изобретения своих велосипедов. Подключение Twig - первый шаг, но далеко не последний
Вам обязательно стоит посвятить время изучению кода популярных проектов. Это многое может рассказать вам о подходах к решениям, паттернах и т.п. Конечно, параллельно нужно будет выяснять значения массы используемых терминов чтобы лучше понимать происходящее, это тоже пойдёт вам на пользу.
Смотрите как развиваются другие технологии, которые вы используете, таблицами сейчас не верстают :)
Рекомендую рассмотреть вариант использования для написания кода нормальной IDE, к примеру PHPStorm, это существенно улучшит вашу производительность и убережёт от массы ошибок


Теперь более предметно:

Оформление кода:

Вы утверждаете что код соответствует PSR-2 (кстати, актуальный - PSR-12), однако есть мелкие огрехи (раздел 2.2).

Оформление composer.json:

Лучше указывать требования к платформе, в вашем случае - как минимум версию PHP т.к. platform requirements проверяются Composer'ом при установке.

Поскольку ваш проект - не библиотека, то composer.lock тоже должен быть частью репозитория.

Про настройки autoload'а вам уже сказали, обращу только внимание на то что сейчас структура репозитория отражает PSR-0, а не актуальный PSR-4, при использовании PSR-4 ваш код проекта лежал бы в src.

Организация репозитория

Код проекта должен лежать за пределами web root, поэтому вам явно не хватает папки public с единственным index.php

Конфигурация

Конфигурирование через константы - весьма устаревший подход. К примеру представьте что вы разворачиваете этот код на production сервере и вам нужно сменить данные для подключения к базе данных не создавая локальных изменений в рабочей копии. Сейчас у вас это не получится. Выход: читаем про
12 factor app и, в частности, раздел config, а затем подключаем в проект, к примеру, vlucas/phpdotenv или symfony/dotenv

Сервисы

Использование bootstrap.php - хорошо, но для организации работы с сервисами сейчас как правило используются dependency injection контейнеры, даже PSR-11 для них есть. В текущем виде ваш подход слабо расширяем, а передача сервисов через глобальные переменные - так себе идея по многим причинам.

Понятно что вворачивать DI container для примера на три файлика - overkill, но с самим подходом вам следует ознакомиться. Из реализаций самая популярная сейчас - symfony/dependency-injection, но есть и альтернативы.

Автолоадер

Про autoload.php вам уже сказали, вместо него стоит корректно конфигурировать автозагрузку в composer.json и полагаться на то что Composer вам сгенерирует. Он ведь умеет всё это и оптимизировать при необходимости.

Внешние пакеты

Для новых проектов рекомендуется выбирать актуальные и поддерживаемые версии пакетов. Хотя Twig 1.x ещё поддерживается, тем не менее актуальная версия - 3.x.

Обработка ошибок

Попробовать сделать это самостоятельно, безусловно, полезно чтобы лучше разобраться как это работает, но для реальной работы лучше полагаться на проверенные решения, к примеру filp/whoops или symfony/error-handler

Типы данных

Важно помнить что PHP с версии 7.0 поддерживает указание скалярных типов для аргументов и
возвращаемых значений, с 7.1 - nullable типы и class constant visibility, а с 7.4 - типизированные свойства. Всё это гораздо надёжнее чем описание типов через аннотации и этим стоит пользоваться.

Также повсеместно в коде используется нестрогое сравнение, тогда как очень желательно всегда использовать строгое (документация).

Data Objects

Сейчас Place и PlaceFilter по сути являются data объектами т.е. они не содержат самостоятельной логики, а просто переносят некие данные. При этом оба этих класса имеют пустые конструкторы (которые, кстати, лучше убирать), а загрузка данных организована через setter методы. Это позволяет изменить данные в них в произвольные моменты времени что вряд ли является желаемым поведением. Вместо этого подобные объекты лучше организовывать в виде immutable объектов (статья с примерами) чтобы не позволять ненужного нарушения целостности данных. Альтернативно, к примеру, для PlaceFilter может лучше подходить использование паттерна
    Builder, хотя в википедии не самый лучший пример.

Именование

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

Оптимизации

Понятно что это мелочи, но явно видно что компиляцию запросов (1, 2) можно кэшировать вместо того чтобы перекомпилировать каждый раз.

References

PDOStatement::bindParam() принимает аргумент $variable как reference, а в коде в этот аргумент передаётся выражение что недопустимо.

Английский язык

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