Я из среды С#, и я начинаю изучать PHP в школе. Я использую для установки своих свойств на С#, как это.
public int ID { get; set; }
Что эквивалентно этому в php?
Спасибо.
Я из среды С#, и я начинаю изучать PHP в школе. Я использую для установки своих свойств на С#, как это.
public int ID { get; set; }
Что эквивалентно этому в php?
Спасибо.
Нет, хотя есть некоторые предложения по внедрению, которые в будущих версиях. Пока вам, к сожалению, нужно вручную объявить все геттеры и сеттеры.
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
Mchi прав, но есть и другой способ сделать это, используя единую функцию
private $ID;
public function ID( $value = "" )
{
if( empty( $value ) )
return $this->ID;
else
$this->ID = $value;
}
Но этот подход в значительной степени связан с тем, что вы делаете в С#. но это только альтернатива
Или попробуйте использовать php __set и __get в своем классе подробнее здесь
Спасибо за ваши ответы всем. Это помогло мне создать что-то вроде этого:
В моем родительском классе:
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:: existsMethod - это метод, который просто проверяет, существует ли данный защищенный метод.
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;
Я был вдохновлен С#:)
Что вы думаете об этом, ребята?
Вот мой 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);
}
}
Другой пример с использованием имени функции Variable
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
private $ID;
public function getsetID($value = NULL)
{
if ($value === NULL) {
return $this->ID;
} else {
$this->ID = $value;
}
}
Я знаю, что я немного опаздываю на вечеринку по этому вопросу, но у меня был тот же вопрос/думал сам. Как разработчик С#, который выполняет PHP, когда требуется задание, я хочу иметь простой способ создания свойств, просто я смог бы на С#.
В этот день я взломал первый черновик, который позволяет создавать поля поддержки и указывать их аксессуры или иметь чистых аксессуаров без поля поддержки. Я буду обновлять свой ответ по мере развития кода и предоставления ссылки, когда я получу его в состоянии, в котором он может быть импортирован как пакет композитора.
Для простоты я создал функциональность как черту 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;
}
}
Вот быстрый unit test, который я создал с использованием формата 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; });
это PHP; вам не нужно устанавливать set
class MyClass {
public $ID;
}
$object = new MyClass();
$object->ID = 'foo';
echo $object->ID;
будет работать