Объектно-ориентированные лучшие практики PHP

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

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

$object->name = "x";

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

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

Это корректно?

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

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

}

Затем отправьте ему массив? Это было бы лучшей практикой? или кто-то мог рекомендовать лучшую практику?

10
задан Rikesh 21 February 2015 в 09:39
поделиться

6 ответов

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

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

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

23
ответ дан 3 December 2019 в 13:14
поделиться

Я полностью согласен с 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;
  }
}

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

6
ответ дан 3 December 2019 в 13:14
поделиться

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

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 () и создаете другой класс. для обработки всей логики сохранения.

4
ответ дан 3 December 2019 в 13:14
поделиться

С более общей точки зрения как прямой доступ ($ 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

1
ответ дан 3 December 2019 в 13:14
поделиться

У вас должны быть методы установки / получения. Они неприятны, но вам не обязательно писать их самостоятельно. 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 или получать. Итак, теперь вы можете устанавливать / получать (и неявно объявлять) переменные следующим образом:

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

echo $object->getName(); //Outputs Bob
echo $object->getHairColor(); //Outputs Green

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

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

, что делает код простым для написания и чтения.

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

30
ответ дан 3 December 2019 в 13:14
поделиться

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

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

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

2
ответ дан 3 December 2019 в 13:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: