Для чого потрібні інтерфейси в php

У цій замітці, постараюся, коротко, пояснити в яких випадках варто використовувати інтерфейси в PHP і привести приклад практичного їх використання.

Інтерфейси варто створювати коли є спільне завдання і кілька варіантів її вирішення, що застосовуються в залежності від ситуації. Наприклад завдання збереження даних, а в якості рішення збереження даних:
  • в базу даних;
  • в файл;
  • в сесію і ін.

В даному випадку є сенс створити один загальний інтерфейс з обов'язковими методами на кшталт insert () - безпосереднє збереження даних. Залежно від місця зберігання даних, кожен клас буде по своєму реалізовувати збереження даних, але називатися даний метод завжди буде insert (), якщо ми пропишемо його в інтерфейсі.
Після створення інтерфейсу потрібно створити кілька класів-сервісів його реалізують (імплементують).


Для початку, давайте розглянемо приклад без використання інтерфейсу.

При створенні програми згідно ООП, потрібно відокремлювати логіку від функціоналу, розбиваючи завдання на окремі класи.
Припустимо є 3 класу:
- Date (загальний клас, який одержує дані і використовує методи допоміжного класу (сервісу) для їх збереження);
- saveDb (клас зберігає дані в базу даних);
- saveFile (клас зберігає дані в файл)
в даному прикладі, для збереження даних, методу date () класу Date, в якості аргументу, потрібно передати екземпляр конкретного класу - saveDb або saveFile.

Недолік даного підходу в тому, що клас перевіряючий дані і клас зберігає дані сильно пов'язані між собою. У прикладі, ми вказуємо, що аргумент методу date () - це екземпляр класу працює з базою даних. Далі використовуються потрібні методи даного класу (saveDb) на зразок insertInto ().
А що, якщо знадобиться зберегти дані не в БД, а в файл. В цьому випадку потрібно буде міняти весь метод date (), адже в іншого класу можуть бути зовсім інші методи, а не метод insertInto () і весь принцип побудови іншого класу може сильно відрізнятися. Може бути, там навіть буде передбачена своя валідація і метод validate () класу Date виявиться зайвим.

Ось в таких випадках і використовуються інтерфейси. Вони допомагають у створенні шаблонів для класів, які будуть використовуватися в додатку і мати загальні методи роблять одні й ті ж завдання, але своїм способом. Інтерфейси дозволяють швидше розібратися в коді і легше його підтримувати. Так само, вони допомагають створювати слабку зв'язаність між класами, що можна продемонструвати на прикладі:


У моєму спрощеному прикладі видно, що інтерфейс зобов'язує реалізують його класи мати метод insert (). який (припустимо) безпосередньо займаються вставкою даних. А крім нього, кожен клас може мати інші необхідні для його роботи методи. Для класу saveDb. це, наприклад, метод connectDb (). створює з'єднання з базою даних. Для тестування, я зробив висновок повідомлень при спрацьовуванні методу insert ().

Таким чином, при роботі з даними, в конструктор потрібного класу або інший метод, ми можемо передавати клас-сервіс, вказуючи, що він відноситься до певного інтерфейсу і бути впевненими, що для всіх класів даної групи використовуються однакові методи. Інформацію про ці методи (документацію), до речі, можна вказати прямо в коді інтерфейсу біля відповідних методів, тим більше, що там буде набагато менше рядків ніж в реалізують його класах.

В даному прикладі, замість залежності від конкретного класу (saveDb) передається залежність від інтерфейсу Save:

Код класу Date не залежить від конкретного реалізатора, а тільки від інтерфейсу. Варто зазначити, що даний приклад побудований на базі патерну "Dependency injection", що перекладається як "впровадження залежності".
Інтерфейс забезпечує наявність зазначених в ньому методів у всіх класах які його реалізують. Тому можна бути впевненим, що виклик методу insert ():

приведе до збереження даних. При цьому місце зберігання залежить від реалізації даного методу в кожному з класів. Так, метод insert () класу saveDb зберігає в базу даних, метод insert () класу saveFile зберігає в файл і тд. Виконайте код даного прикладу і побачите, що клас Date відпрацював з усіма класами інтерфейсу Save і при цьому, код самого класу Date ніяк не довелося міняти.

Потрібен сайт? Бажаєте запропонувати співпрацю? Звертайтеся - контакти.

Здравствуйте! По 1-му пункту - якщо сторінка перезавантажується, то значить pjax не працює. Спробуйте дію actionSubscription змінити таким чином: public function actionSubscription ()

Шукав по всьому коду і так і не знайшов де задається, що спочатку викликати контролер footer, а потім header, для чого це зроблено зрозуміло, щоб додавати підключення скриптів і стілейможет ви.

Для показу цього елементу вам необхідно встановити FlashPlayer та включити в броузері Java Script.