Скажите, что у меня есть класс, который представляет человека, переменная в том классе была бы $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
}
Затем отправьте ему массив? Это было бы лучшей практикой? или кто-то мог рекомендовать лучшую практику?
Использование явных методов получения и установки для свойств объекта (как в примере, который вы привели для set_name
) вместо прямого доступа к ним дает вам (среди прочего) следующие преимущества:
По указанным выше причинам это можно считать наилучшей практикой, хотя на самом деле это не обязательно (и может считаться излишним для некоторых применений; например, когда ваш объект выполняет очень небольшую «обработку» но просто действует как заполнитель для «данных»).
Я полностью согласен с 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;
}
}
Очевидно, вы можете использовать метод установки в конструкторе (обратите внимание на повторяющийся код для средства установки пола).
Чтобы перейти к полному ООП, вы должны сделать что-то подобное:
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 () и создаете другой класс. для обработки всей логики сохранения.
С более общей точки зрения как прямой доступ ($ 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
У вас должны быть методы установки / получения. Они неприятны, но вам не обязательно писать их самостоятельно. 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 вместе с приведенным выше кодом.
В противовес ответу ChristopheD, если ваша переменная экземпляра предназначена исключительно для частного использования, я бы не стал писать геттер и сеттер, а просто объявил бы переменную экземпляра частной.
Если другим объектам требуется доступ к объекту, вы всегда можете добавить геттер. (Это создает другую проблему, поскольку другие классы могут изменять объект, возвращаемый геттером. Но ваш геттер всегда может вернуть копию переменной экземпляра.)
Кроме того, с помощью геттера. / setter также защищает другие части того же класса от информации о его собственной реализации, что иногда мне кажется очень полезным!