it-swarm.com.ru

получить набор свойств в php

Я из среды C #, и я начинаю изучать PHP в школе .. Я привык устанавливать свои свойства в C # следующим образом.

public int ID { get; set; }

Что эквивалентно этому в php?

Благодарю.

19
Jeppe Strøm

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

private $ID;

public function setID($ID) {
  $this->ID = $ID;
}

public function getID() {
  return $this->ID;
}

для некоторой магии (PHP любит магию), вы можете искать __set и __getмагические методы.

Пример

class MyClass {

  private $ID;

  private function setID($ID) {
    $this->ID = $ID;
  }

  private function getID() {
    return $this->ID;
  }


  public function __set($name,$value) {
    switch($name) { //this is kind of silly example, bt shows the idea
      case 'ID': 
        return $this->setID($value);
    }
  }

  public function __get($name) {
    switch($name) {
      case 'ID': 
        return $this->getID();
    }
  }

}


$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
20
Mchl

Спасибо всем за ответы. Это помогло мне создать что-то вроде этого:

В моем родительском классе:

public function __get($name){

    if (ObjectHelper::existsMethod($this,$name)){
        return $this->$name();
    }

    return null;
}

public function __set($name, $value){

    if (ObjectHelper::existsMethod($this,$name))
        $this->$name($value);
}

ObjectHelper :: existMethod - это метод, который просто проверяет, существует ли данный защищенный метод.

private $_propertyName = null;

protected function PropertyName($value = ""){

    if (empty($value)) // getter
    {
        if ($this-> _propertyName != null)
            return $this->_propertyName;
    }
    else // setter
    {
        $this-> _propertyName = $value;
    }

    return null;
}

Так что я могу использовать что-то вроде этого в любом классе:

$class = new Class();
$class->PropertyName = "test";
echo $class->PropertyName;

Я был вдохновлен C # :)

Что вы думаете об этом, ребята? 

Вот мой ObjectHelper, если кто-то хотел бы использовать его:

namespace Helpers;

use ReflectionMethod;

class ObjectHelper {

public static function existsMethod($obj, $methodName){

    $methods = self::getMethods($obj);

    $neededObject = array_filter(
        $methods,
        function ($e) use($methodName) {
            return $e->Name == $methodName;
         }
    );

    if (is_array($neededObject))
        return true;

    return false;
}

public static function getMethods($obj){

    $var = new \ReflectionClass($obj);

    return $var->getMethods(ReflectionMethod::IS_PROTECTED);
}
}
6
Piotr Czyż

Mchi правильно, но есть другой способ сделать это с помощью одной функции

    private $ID;

public function ID( $value = "" )

{

    if( empty( $value ) )

        return $this->ID;

    else

        $this->ID = $value;

}

Но да, этот подход в значительной степени соответствует тому, что вы делаете в c #. но это только альтернатива

Или попробуйте использовать php __set и __get в вашем классе.

http://php.net/manual/en/language.oop5.overloading.php

6
Jaspreet Chahal

Другой пример с использованием имени переменной функции

class MyClass {

  private $ID;
  protected $ID2;

  private function setID($ID) {
    $this->ID = $ID;
  }
  private function getID() {
    return $this->ID;
  }
  private function setID2($ID2) {
    $this->ID2 = $ID2;
  }

  private function getID2() {
    return $this->ID2;
  }
  public function __set($name,$value) {
    $functionname='set'.$name;
    return $this->$functionname($value);
  }
  public function __get($name) {
    $functionname='get'.$name;
    return $this->$functionname();
  }

}


$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
$object->ID2 = 'bar'; //setID2('bar') will be called
3
user3397560
private $ID;

public function getsetID($value = NULL)
{
    if ($value === NULL) {
        return $this->ID;
    } else {
        $this->ID = $value;
    }
}
1
DanAlexson90

Я знаю, что немного опоздал на вечеринку по этому вопросу, но у меня был тот же самый вопрос/мысль сама. Как разработчик C #, который делает PHP, когда работа требует, я хочу иметь простой способ создавать свойства, как я мог бы в C #.

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

Для простоты я создал функциональность как черту PHP, чтобы вы могли добавить ее к любому классу, который вам нужен, вместо того, чтобы расширять базовый класс. Со временем я надеюсь расширить эту функциональность, чтобы различать внешние публичные вызовы свойств и защищенные/частные вызовы.

Вот код самой черты:

trait PropertyAccessorTrait
{
    private static $__propertyAccessors = [];

    /* @property string $__propertyPrefix */

    public function __get($name)
    {
        $this->__populatePropertyAcessors($name);

        return $this->__performGet($name);
    }

    public function __set($name, $value)
    {
        $this->__populatePropertyAcessors($name);

        $this->__performSet($name, $value);
    }

    public function __isset($name)
    {
        // TODO: Implement __isset() method.
    }

    public function __unset($name)
    {
        // TODO: Implement __unset() method.
    }

    protected function __getBackingFieldName($name)
    {
        if (property_exists(self::class, '__propertyPrefix')) {
            $prefix = $this->__propertyPrefix;
        } else {
            $prefix = '';
        }

        return $prefix . $name;
    }

    protected function __canget($name)
    {
        $accessors = $this->__getPropertyAccessors($name);

        return $accessors !== null && isset($accessors['get']);
    }

    protected function __canset($name)
    {
        $accessors = $this->__getPropertyAccessors($name);

        return $accessors !== null && isset($accessors['set']);
    }

    protected function __performGet($name)
    {
        if (!$this->__canget($name)) {
            throw new \Exception('Getter not allowed for property: ' . $name);
        }

        $accessors = $this->__getPropertyAccessors($name)['get'];

        /* @var \ReflectionMethod $method */
        $method = $accessors['method'];

        if (!empty($method)) {
            return $method->invoke($this);
        }

        return $this->{$this->__getBackingFieldName($name)};
    }

    protected function __performSet($name, $value)
    {
        if (!$this->__canset($name)) {
            throw new \Exception('Setter not allowed for property: ' . $name);
        }

        $accessors = $this->__getPropertyAccessors($name)['set'];

        /* @var \ReflectionMethod $method */
        $method = $accessors['method'];

        if (!empty($method)) {
            return $method->invoke($this, $value);
        }

        $this->{$this->__getBackingFieldName($name)} = $value;
    }

    protected function __getPropertyAccessors($name)
    {
        return isset(self::$__propertyAccessors[$name])
            ? self::$__propertyAccessors[$name]
            : null
            ;
    }

    protected function __getAccessorsFromDocBlock($docblock)
    {
        $accessors = [];

        if (!empty(trim($docblock))) {
            $doclines = null;

            if (!empty($docblock)) {
                $doclines = explode("\n", $docblock);
            }

            if (!empty($doclines)) {
                foreach ($doclines as $line) {
                    if (preg_match('/@(get|set)\\s+(public|private|protected)/', $line, $matches)) {
                        $accessors[$matches[1]]['visibility'] = $matches[2];
                    }
                }
            }
        }

        return $accessors;
    }

    protected function __populatePropertyAcessors($name)
    {
        if ($this->__getPropertyAccessors($name) !== null) return;

        try {
            $property = new \ReflectionProperty(self::class, $this->__getBackingFieldName($name));
        } catch (\ReflectionException $ex) {
            $property = null;
        }

        $accessors = [];

        if ($property != null) {
            $accessors = $this->__getAccessorsFromDocBlock($property->getDocComment());
        }

        try {
            $methodName = 'get' . ucfirst($name);
            $method = new \ReflectionMethod(self::class, $methodName);
            $method->setAccessible(true);
            $accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
        } catch (\ReflectionException $ex) {
            $method = null;
        }


        if ($method !== null || isset($accessors['get'])) {
            $accessors['get']['method'] = $method;
        }

        try {
            $methodName = 'set' . ucfirst($name);
            $method = new \ReflectionMethod(self::class, $methodName);
            $method->setAccessible(true);
            $accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
        } catch (\ReflectionException $ex) {
            $method = null;
        }

        if ($method !== null || isset($accessors['set'])) {
            $accessors['set']['method'] = $method;
        }

        self::$__propertyAccessors[$name] = $accessors;
    }
}

Вот быстрый модульный тест, который я создал с использованием формата Codeception:

<?php

class PropertyAssesorTraitTestClass
{
    use PropertyAccessorTrait;

    private $__propertyPrefix = '_';

    /**
     * @get public
     * @set public
     */
    private $_integer = 1;

    /**
     * @get public
     */
    private $_getonly = 100;

    /**
     * @set public
     */
    private $_setonly;

    private $_customDoubler;

    private function getCustomDoubler()
    {
        return $this->_customDoubler * 2;
    }

    private function setCustomDoubler($value)
    {
        $this->_customDoubler = $value * 2;
    }

    public $publicField = 1234;

    /**
     * @return int
     * @get public
     */
    private function getPureAccessor()
    {
        return $this->publicField;
    }

    /**
     * @param $value
     * @set public
     */
    private function setPureAccessor($value)
    {
        $this->publicField = $value;
    }

    private $_purePrivate = 256;
}

$I = new UnitTester($scenario);
$I->wantTo('Ensure properties are accessed correctly');

$instance = new PropertyAssesorTraitTestClass();
$I->assertSame(1, $instance->integer);

$instance->integer = 2;
$I->assertSame(2, $instance->integer);

$instance->integer = $instance->integer + 1;
$I->assertSame(3, $instance->integer);

$instance->integer++;
$I->assertSame(4, $instance->integer);

$I->assertSame(100, $instance->getonly);
$I->expectException('Exception', function () use ($instance) { $instance->getonly = 50; });

$instance->setonly = 50;
$I->expectException('Exception', function () use ($instance) { $a = $instance->setonly; });

$instance->customDoubler = 100;
$I->assertSame(400, $instance->customDoubler);

$I->assertSame(1234, $instance->publicField);
$instance->pureAccessor = 1000;
$I->assertSame(1000, $instance->publicField);
$instance->publicField = 1234;
$I->assertSame(1234, $instance->publicField);
$I->assertSame(1234, $instance->pureAccessor);

$I->expectException('Exception', function () use ($instance) { return $instance->purePrivate; });
0
rmblstrp