ООП в PHP: изучаем на реальных примерах

Всем привет. Прямо сейчас открыт набор в новую группу курса «Backend-разработчик на PHP». В преддверии старта курса решили поделиться с вами интересной статьей, которую написал наш внештатный автор. Данная статья не имеет отношения к программе курса но, если вы хотите подробнее ознакомиться с курсом и на живом примере увидеть процесс преподавания, приглашаем на бесплатный урок по теме «Сине-зеленый деплой», который состоится 21 апреля.


Лично мне очень нравится ООП в PHP, и возможности, которые оно дает для создания продукта, достаточно велики. Большинство вакансий PHP — разработчика включает в себя требования к владению ООП в разработке. Вы не сможете написать что-то вразумительное на современных PHP фреймворках, таких как Laravel, Symfony, или на таком популярном, как 1C Bitrix, если не владеете хотя бы основами ООП. В интернете существует множество гайдов, что такое ООП, есть некоторые недурные книги и чуть меньше именно по ООП в PHP. В последнее время я перевернул интернет в поисках примеров для студентов и не нашел практически ничего свеженького, что могло бы быть реально полезно.

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

Вступление

Несмотря на большое количество гайдов по ООП, в которых авторы не привязываются конкретно ни к какому языку, сама реализация объектов и классов, а главное, синтаксические возможности языков, разительно различаются. Если современное ООП в JavaScript у разработчиков из статических языков вызывает только раздражение (цитата моего знакомого Java-разработчика «из JavaScript мне нравится только TypeScript, но он потом все равно компилируется в JavaScript, поэтому он мне тоже не нравится») и дело не только в динамической типизации, но и развитии ООП, но с другой стороны ничего нелогичного здесь нет — JavaScript это полноценный, но скриптовый язык программирования, который в итоге через развитие интернета и разросся до неимоверных размеров. Но сейчас речь не о JavaScript или Java, сейчас речь о языке, который находится в своем положении где-то посередине — PHP.

Зачем там вообще в PHP ООП

До какого-то ключевого момента (примерно до 5 версии) в PHP не было полноценной поддержки ООП, хотя классы и объекты поддерживались уже с 3 версии. Конечно, в самом PHP заключаются некоторые фатальные недостатки, большинство из которых все еще остаются в языке даже в новейших версиях (полный список, если вы еще их не читали, можно почитать в этой статье ). Но непонятных статей на темы: «ООП в PHP совсем другое, и это хорошо», «не трогайте OOП в PHP, и вас ждет успех» и так далее много, так что давайте теперь перейдем к самому синтаксису в PHP.

Синтаксические возможности PHP в плане ООП

Если читатель хоть немного программировал в PHP, он знает, что этот язык поддерживает сразу две парадигмы: функциональную и объектно-ориентированную. Эта двойственность языка вроде как никого не смущает, но часто приводит к проблемам в выполнении кода, потому как у множества функций есть двойственный интерфейс, к примеру mysqli:

#процедурный вариант  $connect = mysqli_connect("localhost", "root", "password", "db_example"); # не буду тут приводить обработку ошибок, подключаемся к localhost под root  # с паролем password к базе данных db_example  $res = mysqli_query($connect, "SELECT * from users WHERE id = 1"); $row = mysqli_fetch_assoc($res); echo $row['msg'];  #тот же самый код, только в объектно-ориентированном виде  $mysqli = new connect("localhost", "root", "password", "db_example"); #тоже тут пропущу обработку ошибок $res = $mysqli->query("SELECT * from users WHERE id = 1"); $row = $res->fetch_assoc(); echo $row['msg']; 

Оба эти запроса к базе данных MySQL одинаково успешно выведут нам колонку сообщений данных пользователя с id = 1. Правда, в документации рекомендуется использовать объектно-ориентированный вариант, но зачем же тогда существует процедурный?
Это был только один из примеров. Так какие ООП возможности PHP мы разберем сегодня:

  • Конструктор, создание экземпляра из класса
  • Ключевое слово static
  • Наследование

Классы и экземпляры

Изучение объектно-ориентированной парадигмы часто начинается с изучения экземпляров и классов. Учитывая, что концепция объектно-ориентированного программирования сама по себе пришла к нам из реального мира, здесь можно приводить множество аналогий по типу: абстрактный класс — Автомобиль, экземпляр — «лада седан баклажан 2017 года выпуска».

Что касается PHP, то в нем классическое решение относительно классов->экземпляров, это перенести в класс какой-либо повторяющийся элемент, используя его как шаблон с повторяющимся контентом (ну и в общем примерно в таком же виде работает React с его компонентами, если все немного упростить). Очень часто в гайдах по ООП можно встретить пример с классом User, но сегодня я обращусь к примеру класса Post. Допустим у вас какой-то элементарный новостной сайт с простенькой админкой, в которой можно выкладывать свои новости.

class Post {     #просто предположим, что у нашего поста всего есть изображение     public function __construct($id, $img, $header, $content)     {         $this->img = $img;         $this->header = $header;         $this->content = $content;     }     #здесь я делаю не совсем хорошую вещь, я отдаю представление вместо c html версткой. Но, положим, я не собираюсь развивать этот класс больше     public function return_view()     {         return "     <img  src=" . $this->img . " >     <h3>" . $this->header . "</h3>     <p>" . $this->content . "</p>";      } }   

ООП в PHP часто начинают изучать с создания экземпляров объекта и затем назначения их полей, но я не вижу особого смысла в этом, думаю стоит сразу начать писать классы с конструкторами. Меня долго мучила причина, почему методы конструктора и другие называют именно «магическими», но вся магия состоит в том, что их не нужно вызывать вручную и они «магически» вызываются при создании экземпляра.

После того, как мы создали класс, мы можем его использовать, например в цикле:

require $_SERVER['DOCUMENT_ROOT'] . "/project_forum/classes/Card.class.php"; # подтягиваем файл с классами  echo "<section>"; for ($i = 0; $i < count($post_data["header"]); $i++) {     //здесь у нас цикл будет крутиться до той поры, пока есть заголовки     // предполагается что постов без заголовков у нас нет     $post = new Post($post_data[$img][$i], $post_data[$header][$i], $post_data[$content][$i]);     echo "<div class='post_data'>";     echo $post->return_view();     //выводим наше представление     echo "</div>"; } echo " </section>"; 

Ключевое слово static

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

Наш файл Db.class.php:

 class Db {     public static function getdbconnect()     {         $connect = mysqli_connect("localhost", "root", "", "test_db") or die("Couldn't connect");         $connect->set_charset("utf8");         return $connect;     } }  

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

class User {     public function login()     {         $this->user_name = trim($user_name);         $this->user_password = hash('sha256', $user_password);         $result = Db::getdbconnect()->query("SELECT * FROM users WHERE Name = '$this->user_name'");     } } 

Наследование

Чаще всего наследование подразумевает по собой использование уже имеющегося шаблона класса с целью его расширения. По сути, это можно сравнить с комплектацией автомобилей в реальном мире: если вас интересует только базовая комплектация автомобиля и большего вам и не надо, тогда вы берете автомобиль с минимальным набором функций. Однако если вы много пользуетесь автомобилем и часто попадаете в различные ситуации, вам нужна расширенная функциональность.

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

class User {     # для примера возьму самый минималистичный вариант, которым можно обойтись в таких сервисах     protected $user_email;     protected $user_password;      public function register($user_name, $user_password)     {         // пользователь может зарегистрироваться     }      public function login()     {         #пользователь может зайти на ресурс         # под почтой и паролем, которые он использовал во время регистрации     }      public function logout($user_email, $user_password)     {         # пользователь может покинуть ресурс. Если у нас все написано на сессиях, тогда нам надо ее закончить     }      public function сomment($user_email)     {        #пользователь может оставлять комментарии в любом из постов         #для этого вам скорее всего нужно будет реализовать foreigh ключ     }  }  

Дальше, у нас есть дополнительный функционал у класса Admin:

class Admin extends User {      public function edit()     {         # удаляет комменты со страницы     } }  

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

На этом все. Вот некоторые полезные ссылки:


Узнать подробнее о курсе


FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *