Объекты и классы в PHP

Классы и объекты в PHP

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

В PHP класс определяется с помощью следующего синтаксиса:

class Имя_класса{
  var $имя_свойства;
    /*список свойств*/
  function имя_метода( ){
   /* определение метода */
  }
  /*список методов*/
}

Внутри определения класса можно использовать ключевое слово this для обращения к текущему представителю класса.

Пример

Определение класса, описывающего категории статей, имеющих такие свойства, как название, автор и краткое содержание.

<?
class Articles { // Создаем класс Статей
  var $title;
  var $author;
  var $description;
// метод, который присваивает значения атрибутам класса
  function make_article($t, $a, $d){
    $this->title = $t;
    $this->author = $a;
    $this->description = $d;
  }
//метод для отображения экземпляров класса
  function show_article(){
    $art = $this->title . "<br>" .
           $this->description .
      "<br>Автор: " . $this->author;
    echo $art;
  }
}
?>

Инициализация переменных

В PHP4 можно инициализировать значения с помощью оператора var или с помощью функции-конструктора. С помощью var можно инициализировать только константные значения. Для задания не константных значений используют функцию-конструктор, которая вызывается автоматически, когда объект конструируется из класса. Функция-конструктор должна иметь имя, совпадающее с именем всего класса, в котором она определена.

Пример

При создании объекта «статья» установим его свойства следующим образом: автора – равным строке «Иванов», название и краткое содержание – соответствующим элементам глобального массива $_POST, а дату публикации статьи – текущей дате.

<?
class Articles { // Создаем класс Статей
  var $title;
  var $author = "Иванов";
  var $description;
  var $published;
// метод, который присваивает значения атрибутам класса
 function Articles(){
  $this->title = $_POST["title"];
  $this->description = $_POST["description"];
  $this ->published = date("Y-m-d");
 }
}
?>

В PHP5 конструктор класса именуется _construct. Кроме того, в PHP5 появились и деструкторы – функции, которые вызываются автоматически перед уничтожением объекта. В PHP5 функция-деструктор должна быть названа _destruct.

Объекты

Класс – это описание данных одного типа, данных типа объект. Классы являются как бы шаблонами для реальных переменных. Переменная нужного типа (объект) создается из класса с помощью оператора new. Создав объект, мы можем применять к нему все методы и получать все свойства, определенные в описании класса. Для этого используют такой синтаксис:
$имя_объекта->название_свойства или $имя_объекта->название_метода(список аргументов).
Заметим, что перед названием свойства или метода знака $ не ставят.

<?php
$art = new Articles; 
    // создаем переменную (объект) $art
echo ($art ->title); 
    // выводим свойство (название) переменной (объекта) $art
$another_art = new Articles; 
    // создаем объект $another_art
$another_art->show_article(); 
    // вызываем метод для отображения объекта в браузер
?>

Переменная в PHP имеет только один знак доллара перед именем, поэтому нельзя писать $art->$title. Эта конструкция будет рассмотрена не как обращение к свойству title объекта $art, а как обращение к свойству, имя которого задано переменной $title (например, $art->»").

<?php
$art->title = "Введение в Internet"; 
    // так можно установить значение свойства объекта
$art->$title = "Введение в Internet"; 
    // так нельзя установить значение свойства объекта
$property = "title";
$art->$property = "Введение в Internet"; 
    // так можно установить значение свойства объекта
?>

Создавая класс, мы не можем знать, какое имя будет иметь объект этого класса, тем более что объектов может быть много и все могут иметь разные имена. Соответственно мы не знаем, как обращаться к объекту внутри определения класса. Для того чтобы иметь доступ к функциям и переменным внутри определения класса, нужно использовать псевдопеременную $this. Например, $this->title возвращает значение свойства title у текущего объекта данного класса.

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

Любой класс может быть расширением другого класса. Расширяющий (или производный) класс, кроме тех свойств и методов, которые описаны в его определении, имеет все функции и свойства основного (базового класса). В нашем примере класс программистов – расширяющий, а класс всех людей – базовый. Из класса нельзя удалить никакие существующие свойства и функции, класс можно только расширить. Расширяющий класс в PHP4 всегда зависит только от одного базового класса, поскольку множественное наследование
в PHP не поддерживается. Расширяются классы в PHP с помощью ключевого слова extends.

<?php
class Person { // определяем класс Личности
  var $first_name; // имя личности
  var $last_name; // фамилия личности
  function make_person($t,$a){ 
  // метод устанавливает значения имени и фамилии объекта
    $this->first_name = $t;
    $this->last_name = $a;
  }
  function show_person(){ 
  // метод отображает информацию о личности
    echo ("<p>" . $this->first_name . " " .
      $this->last_name . "</p>");
  }
}
class Programmer extends Person{ 
    // определяем класс Programmer, расширяющий Person
  var $langs = array ("Lisp"); 
    // константным массивом задать переменную в var можно
    function set_lang($new_lang){ 
    // метод добавляет еще один язык к списку известных
    $this->langs[] = $new_lang;
  }
}
?>

Создадим объекта класса programmer с помощью конструкции new и используем функции, заданные для класса Person, т.е. устанавливать и получать имя и фамилию программиста и отображать сведения о нем в браузере:

<?php
$progr = new Programmer;
$progr -> set_lang("PHP"); 
    // методы, определенные для класса Programmer
print_r ($progr->langs);
// методы, определенные для класса Person
$progr->make_person("Bill","Gates");
$progr->show_person();
?>

Конструкторы

<?php
class Programmer extends Person{ 
    // определяем класс Programmer, расширяющий Person
  var $langs = array ("Lisp");
  function Programmer(){ 
    // этот конструктор будет работать и в PHP3, и в PHP4
    $this->make_person("Иван","Петров");
  }
}
?>

Здесь функция Programmer() является конструктором, т.е. выполняется сразу после создания любого представителя класса Programmer, задавая ему имя «Иван» и фамилию «Петров».

<?php
class Programmer extends Person{ 
    // определяем класс Programmer, расширяющий Person
  var $langs = array ("Lisp");
  function Programmer($n = "Иван", 
                      $f = "Петров"){
    // это конструктор
    $this->make_person($n,$f);
  }
}
$default_progr = new Programmer(); 
    // создаст программиста Ивана Петрова
$new_progr = new Programmer("Вася", "Сидоров");
    // создаст программиста Васю Сидорова
print_r($new_progr); 
/* выведет информацию о переменной $new_progr, т.е. свойства объекта и их значения */
?>

Оператор ::

Иногда внутри описания класса возникает необходимость сослаться на функции или переменные из базового класса или ссылаться на функции в классе, ни один представитель которого еще не создан. В PHP4 для этого существует специальный оператор «::»

Например, вот так можно вызвать в описании класса Programmer функцию show_name() из базового класса Person и функцию say_hello(), заданную в описании класса Programmer, когда ни один объект этого класса еще не был создан:

<?php
class Person { // определяем класс Личности
  var $first_name;
  var $last_name;
  function Person($t,$a){ // конструктор
    $this->first_name = $t;
    $this->last_name = $a;
  }
function show_name(){ 
  // метод отображает информацию о личности
    echo ("Меня зовут, " . 
          $this->first_name . " " .
          $this->last_name . "!<br>");
  }
}
class Programmer extends Person{ 
    // определяем класс Programmer, расширяющий Person
  function set_lang($new_lang){ 
    // метод добавляет еще один язык к списку известных
    $this->langs[] = $new_lang;
    Person::show_name(); // правильнее писать parent::show_name();
                         // вызываем функцию из базового класса
    echo "И я знаю теперь еще и " . 
          $new_lang;
  }
  function show_name(){
  echo ("Я программист, " . 
        $this->first_name . " " .
        $this->last_name . "!<br>");
  }
  function say_hello(){
    echo "Привет!<br>";
  }
}
Programmer::say_hello(); 
    // вызываем функцию, когда ни один объект ее класса еще не создан
$new_progr = new Programmer("Вася","Сидоров");
$new_progr->set_lang("PHP");
?>

В результате работы этой программы получим следующее:

Привет!
Меня зовут Вася Сидоров!
И я знаю теперь еще и PHP

С помощью команды Programmer::say_hello(); мы вызываем функцию say_hello класса Programmer как таковую, а не как метод, применяемый к объекту данного класса. В этот момент переменных класса нет. Поэтому функции, вызываемые до создания объекта, не могут пользоваться переменными класса и конструкцией this, но могут пользоваться локальными и глобальными переменными.

В определении класса Programmer мы переопределили функцию show_name(), поэтому вызвать функцию show_name()
из базового класса Person можно только с помощью оператора «::» Вообще говоря, внутри определения класса мы можем вызывать любые методы и свойства, заданные в его базовом классе с помощью обычного $this, если только порожденный класс не переопределяет эти свойства и методы, как в нашем примере.

Объектная модель PHP5

Кроме нового названия для конструкторов и появления деструкторов в PHP5 произошло еще достаточно много изменений.

Некоторые из них:

  • Передача значений параметров класса и присвоение объектов происходит по ссылке, а не по значению, как это было в PHP4.
  • В PHP5 если создаются две равные переменные типа объект, то они указывают на одно значение и изменяются одновременно
    - механизм создания копий — клонирование.

  • В PHP4 все методы и переменные класса доступны извне, т.е. они всегда являются открытыми.
    В PHP5 переменные и методы можно делать открытыми (доступными отовсюду),
    закрытыми (доступными только внутри класса) и защищенными (доступными внутри класса и в его производных классах)

Решение задачи

Для начала создадим форму, где пользователь выбирает, что он хочет создать,
– описание статьи или человека (точнее, это будут две формы):

<form action="task1.php">
Создать описание статьи: <input type=submit
    name=art_create
    value="Create Article">
</form>
<form action="task1.php">
Создать описание личности: <input 
   type=submit name=pers_create 
   value="Create Person">
</form>

Теперь напишем файл для обработки этих форм. В нем создадим два класса – статьи и личности. У каждого класса имеется метод для инициализации его переменных и метод для отображения объектов данного класса. При решении задачи будут использованы две функции, встроенные в PHP для работы с классами и объектами. Это функция get_class(объект), возвращающая имя класса, экземпляром которого является объект, переданный ей в качестве параметра. И функция get_class_vars(имя класса), которая возвращает массив всех свойств класса и их значений по умолчанию. Аналогично можно получить массив имен всех методов класса: get_class_methods(имя класса)

<?php
// Создаем классы Статей и Личностей. Статья имеет заголовок, автора и 
// описание. Личность имеет имя, фамилию и e-mail
class Article {
  var $title;
  var $author;
  var $description;
// метод, который присваивает значения атрибутам класса, функция-конструктор
  function Article($t="Название отсутствует",
      $a="Автор отсутствует",
      $d="Описание отсутствует"){
    $this->title = $t;
    $this->author = $a;
    $this->description = $d;
  }
//метод для отображения экземпляров класса
  function show(){
   $art = "<h2>$this->title</h2><font
   size=-1>$this->description</font><p>Автор:
   $this->author</p>";
    echo $art;
  }
}
// Определение класса Личностей
class Person {
  var $first_name;
  var $last_name;
  var $email;
//метод, который присваивает значения атрибутам класса, функция-конструктор
  function Person($t="Имя не введено",
    $a="Фамилия не введена",$d="Email не указан"){
    $this->first_name = $t;
    $this->last_name = $a;
    $this->email = $d;
  }
//метод для отображения экземпляров класса
  function show(){
    $art = "<h2>$this->first_name</h2><font
      size=-1>$this->last_name</font><p>Автор:
$this->email</p>";
    echo $art;
  }
}
// Далее следует собственно создание и отображение экземпляров выбранного класса
if (isset($_GET["art_create"])){ //Если была выбрана статья
  $art = new Article; // создаем представителя класса статей
  $art_vars = get_class_vars(get_class($art)); //какие аргументы этого класса нужно задать
  Make_form($art,$art_vars,"art_create"); //вызов функции
                      // создания формы
  if (isset($_GET["create_real"])){ Show_($art_vars); }
  // если данные этой формы отправлены, то вызываем функцию показа
}
//то же самое, если была выбрана личность
if (isset($_GET["pers_create"])){
  $art = new Person;
  $art_vars = get_class_vars(get_class($art));
  Make_form($art,$art_vars,"pers_create");
  if (isset($_GET["create_real"])){ Show_($art_vars); }
}
// функция создания формы
function Make_form($art,$art_vars,$glob){
  $str = "<form>";   // html код формы записывается в строчную переменную $str
  //перебираем список переменных класса объекта $art
  foreach ($art_vars as $var_name => $var_value){
    $str .="$var_name<input type=text name=$var_name><br>";
    //создаем элемент формы с именем свойства класса
  }
  $str .= "<input type=hidden name=$glob>"; // чтобы не забыть, что мы создаем
  $str .= "<input type=submit name=create_real
    value='Create and Show'></form>";
echo "$str";   // выводим форму
}
// функция показа объекта
function Show_($art_vars){
  global $art;           //используется глобальное имя объекта
  $k = count($art_vars); //число свойств класса (переменных в форме)
  $p=0; //вспомогательная переменная
  foreach ($art_vars as $name => $value){
    $p++;
      if ($_GET["$name"]=="") $val= $art->$name;
      else $val = $_GET["$name"];
      if ($p<>$k) $par .='"'. $val.'",';
      else $par .='"'. $val.'"';
  }
  $const=get_class($art);
  $par = '$art->'.$const ."(" .$par.");";
  // теперь $par представляет собой php-код для вызова
  // метода класса $art, изначально записанного в $par например,
  // $art->Person('Vasia','Petrov','vas@intuit.ru');
  eval($par); // функция eval выполняет код,
              // содержащийся в $par
  $art->show();
}
?>

Комментариев: 6

  • 01.04.2012 Тим:

    Мегареспект Вам, братья! Даже не представляете, что за чудо эта статья!

  • 09.02.2013 Андрей:

    зачем простые вещи объяснять так сложно?

    зачем такие сложные примеры?..

    не понятно.

    тема статьи — Объекты и классы в PHP

    а примеры включают в себя кучу тем. От инициализации переменных до выполнения кода в коде. мрак.

    не понравилось.

    • 18.02.2013 Кирилл:

      Андрей, статья позаимствована с интуита сто лет назад, мне и самому она сейчас «не очень» :) , так что держу в паблике можно сказать для истории.

  • 21.02.2013 Анатолий:

    Очень запутанное и заумное определение объекта. А вот еще определение «Объект — это совокупность данных (свойств) и функций (методов) для их обработки. Данные и методы называются членами класса. Вообще, объектом является все то, что поддерживает инкапсуляцию.»- с PHP.su. Тоже еще не дано определение инкапсуляции, а уже оно встречается в определении неизвестного понятия.

  • 10.04.2015 Дмитрий:

    А как передать две переменные из инпута в функцию класса на другой страничке?

  • 12.05.2016 Сергей:

    Замечательная, вразумительная статья. Автору спасибо!


Добавление комментария:

 css.php