Можно ли создать свойства экземпляра динамично в PHP?

Вы можете создать шаблон регулярного выражения, сначала удалив пробелы в искомой строке, а затем поместив ' *' (любое количество пробелов) между каждым символом. Поскольку вы хотите использовать любой специальный символ в строке поиска, мы также избегаем их:

import re

def find_with_spaces(pattern, text):
    pattern = pattern.replace(' ', '')
    pattern_re = re.compile(' *'.join(map(re.escape, pattern)))

    m = pattern_re.search(text)
    if m:
        return m.start(), m.end()


s1= ' first words s { r * n g? last words '
s2= 's{r*ng?'

start, end = find_with_spaces(s2, s1)
print(start, end)
print(s1[start:end])

# 13 25
# s { r * n g?

Шаблон регулярного выражения, созданный и использованный функцией в этом случае, был r's *\{ *r *\* *n *g *\?'. Обратите внимание, что конечный индекс равен 25, а последний '?' с индексом 24 - это позволяет вам использовать s1[start:end] для получения соответствующей подстроки.

s3= ' * ng?la'
start, end = find_with_spaces(s3, s1)
print(start, end)
print(s1[start:end])

# 19 28
# * n g? la
59
задан outis 11 July 2012 в 22:03
поделиться

8 ответов

В некотором роде. Существуют магические методы, которые позволяют вам подключить свой собственный код для реализации поведения класса во время выполнения:

class foo {
  public function __get($name) {
    return('dynamic!');
  }
  public function __set($name, $value) {
    $this->internalData[$name] = $value;
  }
}

Это пример динамических методов получения и установки, он позволяет вам выполнять поведение при каждом обращении к свойству объекта. Например,

print(new foo()->someProperty);

напечатает, в этом случае, «динамически!» и вы также можете присвоить значение произвольно названному свойству, и в этом случае метод __set () вызывается без предупреждения. Метод __call ($ name, $ params) делает то же самое для вызовов метода объекта. Очень полезно в особых случаях. Но большую часть времени вы будете обходиться с:

class foo {
  public function __construct() {
    foreach(getSomeDataArray() as $k => $value)
      $this->{$k} = $value;
  }
}

... потому что, в основном, все, что вам нужно, - это сбросить содержимое массива в соответствующие поля классов один раз или, по крайней мере, в очень явные моменты выполнения. дорожка. Так, http://php.net/manual/en/language.oop5.overloading.php

61
ответ дан 24 November 2019 в 18:22
поделиться

Это именно то, что вы хотите. Можете ли вы динамически изменить класс ? На самом деле, нет. Но можете ли вы создать свойства объекта динамически, как в одном конкретном экземпляре этого класса? Да.

class Test
{
    public function __construct($x)
    {
        $this->{$x} = "dynamic";
    }
}

$a = new Test("bar");
print $a->bar;

Выходы:

dynamic

Таким образом, свойство объекта с именем «bar» было динамически создано в конструкторе.

23
ответ дан 24 November 2019 в 18:22
поделиться

Да, вы можете.

class test
{
    public function __construct()
    {
        $arr = array
        (
            'column1',
            'column2',
            'column3'
        );

        foreach ($arr as $key => $value)
        {
            $this->$value = '';
        }   
    }

    public function __set($key, $value)
    {
        $this->$key = $value;
    }

    public function __get($value)
    {
        return 'This is __get magic '.$value;
    }
}

$test = new test;

// Results from our constructor test.
var_dump($test);

// Using __set
$test->new = 'variable';
var_dump($test);

// Using __get
print $test->hello;

Выходные данные

object(test)#1 (3) {
  ["column1"]=>
  string(0) ""
  ["column2"]=>
  string(0) ""
  ["column3"]=>
  string(0) ""
}
object(test)#1 (4) {
  ["column1"]=>
  string(0) ""
  ["column2"]=>
  string(0) ""
  ["column3"]=>
  string(0) ""
  ["new"]=>
  string(8) "variable"
}
This is __get magic hello

Этот код установит динамические свойства в конструкторе, к которым затем можно получить доступ через $ this-> column , Также рекомендуется использовать магические методы __get и __set для работы со свойствами, которые не определены в классе. Более подробную информацию о них можно найти здесь.

http://www.tuxradar.com/practicalphp/6/14/2

http: //www.tuxradar. com / PracticalPHP / 6/14/3

7
ответ дан 24 November 2019 в 18:22
поделиться

Вы можете использовать переменную экземпляра, чтобы действовать как держатель для произвольных значений, а затем использовать __get Волшебный метод извлечения их как обычных свойств:

class My_Class
{
    private $_properties = array();

    public function __construct(Array $hash)
    {
         $this->_properties = $hash;
    }

    public function __get($name)
    {
         if (array_key_exists($name, $this->_properties)) {
             return $this->_properties[$name];
         }
         return null;
    }
}
7
ответ дан 24 November 2019 в 18:22
поделиться

Вы можете:

$variable = 'foo';
$this->$variable = 'bar';

Установит атрибут foo объекта, к которому он вызывается, на bar .

Вы также можете использовать функции:

$this->{strtolower('FOO')} = 'bar';

Это также установит foo (не FOO ) до бар .

1
ответ дан 24 November 2019 в 18:22
поделиться

Это действительно сложный способ справиться с таким быстрым развитием. Мне нравятся ответы и магические методы, но, на мой взгляд, лучше использовать генераторы кода, такие как CodeSmith.

Я создал шаблон, который подключается к базе данных, считывает все столбцы и их типы данных и соответственно генерирует весь класс.

Таким образом, у меня есть читаемый код без ошибок (без опечаток). И если ваша модель базы данных изменится, запустите генератор снова ... у меня он сработает.

0
ответ дан 24 November 2019 в 18:22
поделиться

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


/**
 * Create new instance of a specified class and populate it with given data.
 *
 * @param string $className
 * @param array $data  e.g. array(columnName => value, ..)
 * @param array $mappings  Map column name to class field name, e.g. array(columnName => fieldName)
 * @return object  Populated instance of $className
 */
function createEntity($className, array $data, $mappings = array())
{
    $reflClass = new ReflectionClass($className);
    // Creates a new instance of a given class, without invoking the constructor.
    $entity = unserialize(sprintf('O:%d:"%s":0:{}', strlen($className), $className));
    foreach ($data as $column => $value)
    {
        // translate column name to an entity field name
        $field = isset($mappings[$column]) ? $mappings[$column] : $column;
        if ($reflClass->hasProperty($field))
        {
            $reflProp = $reflClass->getProperty($field);
            $reflProp->setAccessible(true);
            $reflProp->setValue($entity, $value);
        }
    }
    return $entity;
}

/******** And here is example ********/

/**
 * Your domain class without any database specific code!
 */
class Employee
{
    // Class members are not accessible for outside world
    protected $id;
    protected $name;
    protected $email;

    // Constructor will not be called by createEntity, it yours!
    public function  __construct($name, $email)
    {
        $this->name = $name;
        $this->emai = $email;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getEmail()
    {
        return $this->email;
    }
}


$row = array('employee_id' => '1', 'name' => 'John Galt', 'email' => 'john.galt@whoisjohngalt.com');
$mappings = array('employee_id' => 'id'); // Employee has id field, so we add translation for it
$john = createEntity('Employee', $row, $mappings);

print $john->getName(); // John Galt
print $john->getEmail(); // john.galt@whoisjohngalt.com
//...

П.С. Получение данных из объекта аналогично, например используйте $ reflProp-> setValue ($ entity, $ value); P.P.S. Эта функция в значительной степени вдохновлена ​​ Doctrine2 ORM , и это потрясающе!

3
ответ дан 24 November 2019 в 18:22
поделиться

Extend stdClass.

class MyClass extends stdClass
{
    public function __construct()
    {
        $this->prop=1;
    }
}

Надеюсь, это то, что вам нужно.

1
ответ дан 24 November 2019 в 18:22
поделиться
Другие вопросы по тегам:

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