Компонента PropertyAccess (доступ к свойству)¶
Компонент PropertyAccess предоставляет функцию для чтения и написания из/в объект или массив, используя простую нотацию строки.
Установка¶
1 | $ composer require symfony/property-access
|
Также вы можете клонировать репозиторий https://github.com/symfony/property-access.
Note
If you install this component outside of a Symfony application, you must
require the vendor/autoload.php
file in your code to enable the class
autoloading mechanism provided by Composer. Read
this article for more details.
Использование¶
Входная точка этого компонента - это фабрика
PropertyAccess::createPropertyAccessor
.
Это фабрика создаст новый экземпляр класса PropertyAccessor
с конфигурацией по умолчанию:
1 2 3 | use Symfony\Component\PropertyAccess\PropertyAccess;
$propertyAccessor = PropertyAccess::createPropertyAccessor();
|
Чтение из массивов¶
Вы можете прочитать массив с помощью метода
PropertyAccessor::getValue
.
Это делается, используя нотации индекса, которые используются в PHP:
1 2 3 4 5 6 7 | // ...
$person = array(
'first_name' => 'Wouter',
);
var_dump($propertyAccessor->getValue($person, '[first_name]')); // 'Wouter'
var_dump($propertyAccessor->getValue($person, '[age]')); // null
|
Как вы можете увидеть, метод вернёт``null``, если индекс не существует.
Вы также можете использовать многомерные массивы:
1 2 3 4 5 6 7 8 9 10 11 12 | // ...
$persons = array(
array(
'first_name' => 'Wouter',
),
array(
'first_name' => 'Ryan',
)
);
var_dump($propertyAccessor->getValue($persons, '[0][first_name]')); // 'Wouter'
var_dump($propertyAccessor->getValue($persons, '[1][first_name]')); // 'Ryan'
|
Чтение из объектов¶
Метод getValue()
очень обширный, и вы можете увидеть все его функции
при работе с объектами.
Доступ к публичным свойствам¶
Чтобы считывать из свойств, используйте нотацию "dot":
1 2 3 4 5 6 7 8 9 10 11 | // ...
$person = new Person();
$person->firstName = 'Wouter';
var_dump($propertyAccessor->getValue($person, 'firstName')); // 'Wouter'
$child = new Person();
$child->firstName = 'Bar';
$person->children = array($child);
var_dump($propertyAccessor->getValue($person, 'children[0].firstName')); // 'Bar'
|
Caution
Доступ к публичным свойствам - это последня опция, используемая PropertyAccessor
.
Она пытается получить доступ к значению, используя методы описанные ниже до
использования свойства напрямую. Например, если у вас есть публичное свойство,
которое имеет метод геттера, то она будет использовать геттер.
Использование геттеров¶
Метод getValue()
также поддерживает чтение, используя геттеры. Этот метод будет создан,
используя общие соглашения об именовании для геттеров. Он camelizes имя свойства (first_name
становится FirstName
) и добавляет к нему префикс get
. Поэтому настоящий метод становится
getFirstName()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // ...
class Person
{
private $firstName = 'Wouter';
public function getFirstName()
{
return $this->firstName;
}
}
$person = new Person();
var_dump($propertyAccessor->getValue($person, 'first_name')); // 'Wouter'
|
Использование хассеров / иссеров¶
На этом всё не останавливается. Если геттер не найден, процесс доступа будет искать иссер или хассер. Этот метод создается, используя тот же способ что и геттеры, что означает, что вы можете сделать что-то вроде этого:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // ...
class Person
{
private $author = true;
private $children = array();
public function isAuthor()
{
return $this->author;
}
public function hasChildren()
{
return 0 !== count($this->children);
}
}
$person = new Person();
if ($propertyAccessor->getValue($person, 'author')) {
var_dump('He is an author');
}
if ($propertyAccessor->getValue($person, 'children')) {
var_dump('He has children');
}
|
Это произведёт: He is an author
Волшебный метод __get()
¶
Метод getValue()
может также использовать волшебный метод __get()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // ...
class Person
{
private $children = array(
'Wouter' => array(...),
);
public function __get($id)
{
return $this->children[$id];
}
}
$person = new Person();
var_dump($propertyAccessor->getValue($person, 'Wouter')); // array(...)
|
Волшебный метод __call()
¶
Наконец, getValue()
может использовать волшебный метод __call()
, но вам нужно
включить эту функцию, используя
PropertyAccessorBuilder
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // ...
class Person
{
private $children = array(
'wouter' => array(...),
);
public function __call($name, $args)
{
$property = lcfirst(substr($name, 3));
if ('get' === substr($name, 0, 3)) {
return isset($this->children[$property])
? $this->children[$property]
: null;
} elseif ('set' === substr($name, 0, 3)) {
$value = 1 == count($args) ? $args[0] : null;
$this->children[$property] = $value;
}
}
}
$person = new Person();
// Включить волшебный метод PHP __call()
$propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
->enableMagicCall()
->getPropertyAccessor();
var_dump($propertyAccessor->getValue($person, 'wouter')); // array(...)
|
Caution
Функция __call()
отключена по умолчанию, вы можете включить её вызвав
PropertyAccessorBuilder::enableMagicCall
см. Включение других функций.
Написание в массивы¶
Класс PropertyAccessor
может делать больше, чем просто читать массивы, он
может также писать в массив. Этого можно достичь, используя метод
PropertyAccessor::setValue
:
1 2 3 4 5 6 7 8 | // ...
$person = array();
$propertyAccessor->setValue($person, '[first_name]', 'Wouter');
var_dump($propertyAccessor->getValue($person, '[first_name]')); // 'Wouter'
// или
// var_dump($person['first_name']); // 'Wouter'
|
Написание в объекты¶
Метод setValue()
имеет такие же функции, как метод getValue()
. Вы можете использовать
сеттеры, волшебный метод __set()
или свойства для установки значений:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | // ...
class Person
{
public $firstName;
private $lastName;
private $children = array();
public function setLastName($name)
{
$this->lastName = $name;
}
public function getLastName()
{
return $this->lastName;
}
public function getChildren()
{
return $this->children;
}
public function __set($property, $value)
{
$this->$property = $value;
}
}
$person = new Person();
$propertyAccessor->setValue($person, 'firstName', 'Wouter');
$propertyAccessor->setValue($person, 'lastName', 'de Jong'); // setLastName is called
$propertyAccessor->setValue($person, 'children', array(new Person())); // __set is called
var_dump($person->firstName); // 'Wouter'
var_dump($person->getLastName()); // 'de Jong'
var_dump($person->getChildren()); // array(Person());
|
Вы можете также использовать __call()
, чтобы устанавливать значения, но вам
нужно включить функцию, см. Включение других функций.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // ...
class Person
{
private $children = array();
public function __call($name, $args)
{
$property = lcfirst(substr($name, 3));
if ('get' === substr($name, 0, 3)) {
return isset($this->children[$property])
? $this->children[$property]
: null;
} elseif ('set' === substr($name, 0, 3)) {
$value = 1 == count($args) ? $args[0] : null;
$this->children[$property] = $value;
}
}
}
$person = new Person();
// Включить волшебный __call
$propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
->enableMagicCall()
->getPropertyAccessor();
$propertyAccessor->setValue($person, 'wouter', array(...));
var_dump($person->getWouter()); // array(...)
|
Написание в массив свойств¶
Класс PropertyAccessor
позволяет обновлять содержание массивов, содержащихся
в свойствах, через методы добавления и удаления (adder и remover).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | // ...
class Person
{
/**
* @var string[]
*/
private $children = array();
public function getChildren(): array
{
return $this->children;
}
public function addChild(string $name): void
{
$this->children[$name] = $name;
}
public function removeChild(string $name): void
{
unset($this->children[$name]);
}
}
$person = new Person();
$propertyAccessor->setValue($person, 'children', array('kevin', 'wouter'));
var_dump($person->getChildren()); // array('kevin', 'wouter')
|
Компонент PropertyAccess ищет методы под названием add<SingularOfThePropertyName>()
и remove<SingularOfThePropertyName>()
. Оба метода должны быть определены. Например,
в предыдущем примере, компонент щет методы addChild()
и removeChild()
, чтобы
получить доступ к свойству children
. Компонент Инфлектор используется, чтобы
найти сингуляр имени свйоства.
Если они доступны, то методы добавления и удаления имеют приоритет перед методом сеттера.
Проверка путей свойства¶
Если вы хотите проверить может ли безопасно быть вызван,
PropertyAccessor::getValue
на самом деле не вызывая этот метод, то вы можете вместо этого использовать
PropertyAccessor::isReadable
:
1 2 3 4 5 | $person = new Person();
if ($propertyAccessor->isReadable($person, 'firstName')) {
// ...
}
|
То же самое возможно для PropertyAccessor::setValue
:
Вызовите метод
PropertyAccessor::isWritable
,
чтобы узнать, можно ли обновить путь свойства:
1 2 3 4 5 | $person = new Person();
if ($propertyAccessor->isWritable($person, 'firstName')) {
// ...
}
|
Смешение объектов и массивов¶
Вы можете также смешивать объекты и массивы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | // ...
class Person
{
public $firstName;
private $children = array();
public function setChildren($children)
{
$this->children = $children;
}
public function getChildren()
{
return $this->children;
}
}
$person = new Person();
$propertyAccessor->setValue($person, 'children[0]', new Person);
// равняется $person->getChildren()[0] = new Person()
$propertyAccessor->setValue($person, 'children[0].firstName', 'Wouter');
// равняется $person->getChildren()[0]->firstName = 'Wouter'
var_dump('Hello '.$propertyAccessor->getValue($person, 'children[0].firstName')); // 'Wouter'
// равняется $person->getChildren()[0]->firstName
|
Включение других функций¶
PropertyAccessor
может быть
сконфигурирован так, чтобы включать дополнительные функции. Чтобы сделать
это, вы можете использовать
PropertyAccessorBuilder
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // ...
$propertyAccessorBuilder = PropertyAccess::createPropertyAccessorBuilder();
// включает волшебный __call
$propertyAccessorBuilder->enableMagicCall();
// включает волшебный __call
$propertyAccessorBuilder->disableMagicCall();
// проверяет, включена ли обработка волшебного __call
$propertyAccessorBuilder->isMagicCallEnabled(); // true or false
// В конце получить сконфигурированый доступ к свойству
$propertyAccessor = $propertyAccessorBuilder->getPropertyAccessor();
// Или всё за раз
$propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
->enableMagicCall()
->getPropertyAccessor();
|
Или вы можете передать параметры напрямую в конструктор (не рекомендуется):
1 2 | // ...
$propertyAccessor = new PropertyAccessor(true); // это включит обработку волшебного __call
|
Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.