Объектно-ориентированные рекомендации PHP

Скажем, у меня есть класс, который представляет человека, переменная в этом классе будет $ name.

Раньше в моих сценариях я создавал экземпляр объекта, а затем задавал имя, просто используя:

$object->name = "x"; 

Однако мне сказали, что это не лучшая практика? То, что у меня должна быть функция set_name () или что-то подобное:

 function set_name($name) { $this->name=$name; } 

Это верно?

Если в этом примере я хочу вставить новую запись «person» в db, как передать всю информацию о человеке, то есть $ name, $ age, $ address, $ phone и т. Д., Чтобы вставить его, я должен делать:

 function set($data) { $this->name= $data['name']; $this->age = $data['age']; etc etc } 

Затем отправьте массив? Будет ли это лучшей практикой? или кто-то может порекомендовать вам наилучшую практику?

Использование явных getters и seters для свойств объекта (например, пример, который вы дали для имени set_name ) вместо прямого доступа к ним дает вам (среди прочего) следующие преимущества:

  • Вы можете изменить внутреннюю реализацию без необходимости изменять внешние вызовы. Таким образом, «внешний» код не нуждается в изменении так часто (потому что вы предоставляете последовательные средства доступа).
  • Вы четко указываете, какие свойства предназначены для использования / вызова извне класса. Это будет очень полезно, если другие люди начнут использовать ваш класс.

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

У вас должны быть методы setter / getter. Это боль, но вам необязательно писать их сами. IDE (например, Eclipse или Netbeans) может автоматически генерировать их для вас, пока вы предоставляете член класса. Если, однако, вы не хотите иметь дело с этим вообще, и вы на PHP5, вы можете использовать его магические методы для решения проблемы:

  protected $_data=array(); public function __call($method, $args) { switch (substr($method, 0, 3)) { case 'get' : $key = strtolower(substr($method,3)); $data = $this->_data[$key]; return $data; break; case 'set' : $key = strtolower(substr($method,3)); $this->_data[$key] = isset($args[0]) ? $args[0] : null; return $this; break; default : die("Fatal error: Call to undefined function " . $method); } } 

Этот код будет запускаться каждый раз, когда вы используете несуществующий метод, начиная с set или get. Таким образом, вы можете теперь установить / получить (и неявно объявить) переменные следующим образом:

 $object->setName('Bob'); $object->setHairColor('green'); echo $object->getName(); //Outputs Bob echo $object->getHairColor(); //Outputs Green 

Нет необходимости объявлять участников или функции setter / getter. Если в будущем вам нужно добавить функциональность в метод set / get, вы просто объявите его, по существу, переопределив магический метод. Кроме того, поскольку метод setter возвращает $ this, вы можете связать их так:

  $object->setName('Bob') ->setHairColor('green') ->setAddress('someplace'); 

который делает для кода, который легко писать и читать.

Единственный недостаток этого подхода состоит в том, что это затрудняет понимание вашей классовой структуры. Поскольку вы по существу объявляете участников и методы во время выполнения, вы должны сбрасывать объект во время выполнения, чтобы увидеть, что он содержит, а не читать класс. Если вашему классу необходимо объявить четко определенный интерфейс (потому что это библиотека и / или вы хотите, чтобы phpdoc генерировал документацию API), я бы настоятельно советовал объявить публичные методы set / get вместе с указанным выше кодом.

Я совершенно согласен с CristopheD (проголосовали). Я бы добавил хорошую практику при создании нового человека .

Обычно используется конструктор, который принимает обязательные поля и устанавливает значения по умолчанию для необязательных полей. Что-то вроде:

 class Person { private $name; private $surname; private $sex; // Male is the default sex, in this case function Person($name, $surname, $sex='m'){ $this->name = $name; $this->surname = $surname; $this->sex = $sex; } // Getter for name function getName() { return $this->name; } // Might be needed after a trip to Casablanca function setSex($sex) { $this->sex = $sex; } } 

Очевидно, вы могли бы использовать метод setter в конструкторе (обратите внимание на дубликат кода для установщика полос).

Чтобы пройти полный ООП, вы должны сделать что-то похожее на:

 class User { private $_username; private $_email; public function getUsername() { return $this->_username; } public function setUsername($p) { $this->_username = $p; } ... public function __construct() { $this->setId(-1); $this->setUsername("guest"); $this->setEmail(""); } public function saveOrUpdate() { System::getInstance()->saveOrUpdate($this); } } 

Если вы хотите сохранить пользователя, вы просто создаете его, присваиваете его значения с помощью Setters и выполняете $ user-> saveOrUpdate () и имеете другой класс для обработки всей логики сохранения.

В качестве контрапункта для ответа ChristopheD, если ваша переменная экземпляра строго предназначена для частного использования, я бы не стал писать getter & setter и просто объявлять переменную экземпляра private.

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

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

С более общей точки зрения как прямой доступ ($ person-> name), так и методы доступа ($ person-> getName) считаются вредными. В ООП объекты не должны делиться знаниями о своей внутренней структуре и выполнять только отправленные им сообщения. Пример:

 // BAD function drawPerson($person) { echo $person->name; // or ->getName(), doesn't matter } $me = getPersonFromDB(); drawPerson($me); // BETTER class Person .... function draw() { echo $this->name; } $me = getPersonFromDB(); $me->draw(); 

больше информации: http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html