Статьи

Обучение ООП в PHP как можно скорее!

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




ООП обозначает O bject Oriented P rogramming. ООП — это парадигма программирования, в которой вы создаете «объекты» для работы. Затем эти объекты могут быть адаптированы к вашим конкретным потребностям для обслуживания различных типов приложений при сохранении одной и той же базы кода. Действительно полезно.

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

Реализация «Авто» скрыта от нас, однако мы можем использовать ее в полном объеме.

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

Основная идея наследования заключается в том, что похожие объекты имеют общие свойства. Таким образом, создав «универсальный» класс, мы можем иметь план для построения наших последующих классов. Представьте, если хотите, свойства автомобиля: цвет, количество колес, мощность, количество мест и т. Д. Имея этот шаблон, мы можем дополнительно специализировать наши автомобили, расширяя этот класс: создавая гоночный автомобиль, обладающий свойством «нитро», или грузовик, у которого есть свойство «трейлер». Суть заключается в следующем: создайте более общий класс, который содержит большинство общих атрибутов, и у вас будет гораздо меньше работы по определению других объектов, лишь немного отличающихся. Вместо того, чтобы переписывать весь код, вы просто расширяете его свойства, экономя много времени в процессе.

Диаграмма наследования для наших классов автомобилей.

Как было объяснено ранее, одним из основных преимуществ использования объектов является то, что нам не нужно раскрывать все его элементы (атрибуты или функции); просто необходимые интерфейсы для работы с ним. Детали, не полезные для использования этих объектов, должны быть скрыты от остальных объектов. Это то, что называется инкапсуляцией.

  • public: означает, что член класса виден и может использоваться / изменяться всеми
  • private: означает, что член класса может использоваться / изменяться только самим классом
  • protected: означает, что член класса может использоваться / модифицироваться только самим классом и возможными подклассами

ПРИМЕЧАНИЕ. По умолчанию в PHP член класса является общедоступным, если он не объявлен как закрытый или защищенный. Проверьте пример здесь .

Полиморфизм является характеристикой ООП, которая позволяет программисту назначать различное значение или использование чему-либо в разных контекстах — в частности, чтобы позволить члену класса выполнять различные задачи в зависимости от контекста, который он использовал. Представьте, что у вас есть класс Person и два подкласса Person: японский и американский. Оба реализуют функцию с именем talk (), но с разными языками и социальным контекстом. И хотя оба они в основном люди (как они происходят от класса Person), их реализация функции talk () сильно отличается. Таким образом, у вас есть два объекта класса Person, в которых функция talk () работает по-разному.

Хорошо, теперь для реальных действий. Мы будем создавать простой класс для обработки изображений и извлечения информации. В течение этого урока я предполагаю, что у вас есть базовое понимание PHP (переменных, создания функций, работы с операторами потока управления и циклами). Чтение руководства по GD PHP избавит вас от любых сомнений относительно функций обработки изображений.

Начнем с определения нашего класса:

1
2
3
4
<?php
class Image {
}
?>

Это просто говорит PHP, что мы начнем определять новый класс с именем «Image». Теперь мы определим конструктор класса. Конструктор — это просто функция, которая вызывается при создании нового объекта. В PHP 5 это может быть достигнуто двумя различными способами: путем создания общедоступной функции с точно таким же именем класса (PHP 4 и выше) или путем создания функции с именем «__construct ()» (только PHP 5):

Следующие два фрагмента кода делают одно и то же:

1
2
3
4
5
6
7
8
<?php
class Image {
    public function Image() {
        echo «We just created and object!»;
    }
}
$image = new Image();
?>
1
2
3
4
5
6
7
8
<?php
class Image {
    function __construct() {
        echo «We just created and object!»;
    }
}
$image = new Image();
?>

ПРИМЕЧАНИЕ. Конструктор класса всегда открыт.

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

Таким образом, первое, что мы должны сделать, это прочитать изображение, каким бы оно ни было. В настоящее время библиотека GD поддерживает несколько типов изображений, таких как jpg, png, gif, bmp и другие; мы просто должны прочитать изображение и определить его тип.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<?php
class Image {
    function __construct($filename) {
         
        // read the image file to a binary buffer
        $fp = fopen($filename, ‘rb’) or die(«Image ‘$filename’ not found!»);
        $buf = »;
        while(!feof($fp))
            $buf .= fgets($fp, 4096);
         
        // create image
        imagecreatefromstring($buf);
    }
}
$image = new Image(«image.png»);
?>

Итак, что мы сделали? Чтобы открыть изображение настолько легко, насколько это возможно, мы будем использовать функцию GD imagecreatefromstring (которая принимает двоичную строку данных в качестве входных данных) вместо, например, imagecreatefromjpeg , imagecreatefrompng или imagecreatefromgif .

Поэтому мы пытаемся открыть файл изображения и присвоить его указатель файла $fp , и, в случае сбоя, прекратить выполнение программы.

1
$fp = fopen($filename, ‘rb’) or die(«Image ‘$filename’ not found!»);

Далее мы создаем пустую строку для хранения наших данных …

1
$buf = »;

… и читать весь файл, объединяя прочитанные данные с вновь созданным содержимым строки.

1
2
while(!feof($fp))
   $buf .= fgets($fp, 4096);

Теперь нам просто нужно создать наше изображение, используя данные, которые мы только что прочитали …

1
imagecreatefromstring($buf);

… и создать объект для использования всех этих функций.

1
$image = new Image(«image.png»);

ПРИМЕЧАНИЕ: jpg, png, gif и большинство файлов изображений должны быть прочитаны в двоичном режиме, поэтому «rb» передается как второй аргумент функции fopen. «r» означает «только для чтения», а «b» означает двоичный файл.

В нынешнем виде наш класс не очень полезен. Поэтому мы будем добавлять некоторые атрибуты и методы, чтобы сделать его более полезным. Итак, мы начнем с 1: определения некоторых внутренних переменных (обратите внимание на объявление «private» видимости перед каждой переменной)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
class Image {
     
    // class atributes (variables)
    private $image;
    private $width;
    private $height;
    private $mimetype;
     
    function __construct($filename) {
         
        // read the image file to a binary buffer
        $fp = fopen($filename, ‘rb’) or die(«Image ‘$filename’ not found!»);
        $buf = »;
        while(!feof($fp))
            $buf .= fgets($fp, 4096);
         
        // create image and assign it to our variable
        $this->image = imagecreatefromstring($buf);
         
        // extract image information
        $info = getimagesize($filename);
        $this->width = $info[0];
        $this->height = $info[1];
        $this->mimetype = $info[‘mime’];
    }
}
$image = new Image(«image.png»);
?>

И 2: метод для отображения изображения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<?php
class Image {
 
    .
    .
    .
     
    public function display() {
        header(«Content-type: {$this->mimetype}»);
        switch($this->mimetype) {
            case ‘image/jpeg’: imagejpeg($this->image);
            case ‘image/png’: imagepng($this->image);
            case ‘image/gif’: imagegif($this->image);
        }
        //exit;
    }
}
$image = new Image($_GET[‘image’]);
?>

На этом шаге мы просто создали некоторые атрибуты класса (изображение, ширина, высота и mimetype) для хранения данных объекта. Затем мы внесли некоторые изменения, чтобы назначить созданное изображение нашему атрибуту класса $image

1
$this->image = imagecreatefromstring($buf)

… и извлек информацию об изображении в наши оставшиеся переменные класса (прочитайте документацию по getimagesize, чтобы полностью понять, как читается информация об изображении):

1
2
3
4
5
// extract image information
$info = getimagesize($filename);
$this->width = $info[0];
$this->height = $info[1];
$this->mimetype = $info[‘mime’];

Затем мы создали функцию, которая выводит изображение в браузер, определяя соответствующие заголовки (подробнее о заголовках http здесь ) и используя соответствующую функцию (с оператором switch) для вывода изображения на основе исходного mimetype изображения (для этого урока) мы будем просто поддерживать jpg, png и gif, но, как я уже говорил, GD поддерживает множество других форматов (подробнее см. документацию php).

Так что это за «$ this» там? «$ this» в PHP относится к самому классу и используется для указания на атрибуты или функции класса. Таким образом, $ this-> image указывает на атрибут класса с именем $ image, а $ this-> image = … изменяет значение атрибута класса. Если бы вы написали $ image = …, вы бы просто создали новую локальную переменную с именем «$ image», доступную исключительно на время действия функции. Это одна из главных вещей, на которую следует обратить внимание при создании классов в PHP.

Наш не очень полезный (пока!) Метод отображения.

Прямо сейчас наш класс не очень полезен. Конечно, мы можем прочитать наше изображение и показать его, но это все. Теперь мы создадим подкласс для создания наших миниатюр. (Нам действительно не нужно создавать подкласс, но мы сделаем это ради учебника, чтобы продемонстрировать наследование и полиморфизм). Итак, для правильной работы наследования нам нужно немного изменить определение нашего суперкласса (Изображение). Нам просто нужно изменить видимость переменных нашего класса с «приватных» на «защищенные». А теперь мы создадим конструктор нашего подкласса.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
class Image {
     
    // class atributes (variables)
    protected $image;
    protected $width;
    protected $height;
    protected $mimetype;
     
    .
    .
    .
}
 
class Thumbnail extends Image {
     
    function __construct($image, $width, $height) {
         
        // call the super-class contructor
        parent::__construct($image);
         
        // modify the image to create a thumbnail
        $thumb = imagecreatetruecolor($width, $height);
        imagecopyresampled($thumb, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height);
        $this->image = $thumb;
    }
}
?>

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

Теперь мы создаем новое изображение для нашего эскиза с шириной и высотой:

1
$thumb = imagecreatetruecolor($width, $height);

Измените размер (измените размер) исходного изображения на новое, чтобы создать миниатюру:

1
imagecopyresampled($thumb, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height);

И, наконец, измените исходное изображение, чтобы оно содержало миниатюру вместо полноразмерного изображения:

1
$this->image = $thumb;

И угадайте, что? Нам не нужно писать новую функцию для отображения миниатюры, потому что применяется тот же принцип, независимо от того, отображаете ли вы полноразмерное изображение или миниатюру. В конце концов, это все еще изображение! Так что нам просто нужно вызвать нашу функцию display (), определенную в суперклассе, и все готово!

Наш законченный класс и соответствующий подкласс.

На этом мы завершаем наш урок. В качестве упражнения я предлагаю вам реализовать функцию для сохранения сгенерированных миниатюр на диск, а не выводить их на лету (где вы должны реализовать эту функцию? В супер- или подклассе?). Удачи и проверьте почтовый индекс, предоставленный для примера использования и полных классов, разработанных здесь (вам нужно иметь сервер на PHP, чтобы протестировать его).