【发布时间】:2012-03-08 09:15:11
【问题描述】:
我来自 C# 环境,我开始在学校学习 PHP。 我习惯于像这样在 C# 中设置我的属性。
public int ID { get; set; }
php中的this相当于什么?
谢谢。
【问题讨论】:
我来自 C# 环境,我开始在学校学习 PHP。 我习惯于像这样在 C# 中设置我的属性。
public int ID { get; set; }
php中的this相当于什么?
谢谢。
【问题讨论】:
没有,尽管在未来的版本中有some proposals for implementing。 不幸的是,现在您需要手动声明所有 getter 和 setter。
private $ID;
public function setID($ID) {
$this->ID = $ID;
}
public function getID() {
return $this->ID;
}
对于一些魔法(PHP 喜欢魔法),您可以查找 __set 和 __get magic methods.
例子
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;
}
但是,是的,这种方法与您在 c# 中所做的几乎是一致的。但这只是一种选择
或者尝试在你的班级中使用 php 的 __set 和 __get 来获得更多信息
【讨论】:
$class->ID(4); $class->ID(''); echo $class->ID(); 将打印 4 ...
function foo(...$args) { if (empty($args)) { return $this->foo; } else { $this->foo = $args[0]; } }
private $ID;
public function getsetID($value = NULL)
{
if ($value === NULL) {
return $this->ID;
} else {
$this->ID = $value;
}
}
【讨论】:
if (func_num_args() === 0) 可以用于此。
另一个使用变量函数名的例子
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
【讨论】:
感谢大家的回答。它帮助我创造了这样的东西:
在我的父类中:
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;
我受到 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);
}
}
【讨论】:
我知道我在这个问题上迟到了,但我自己也有同样的问题/想法。作为一名使用 PHP 的 C# 开发人员,当工作需要时,我希望有一种简单的方法来创建我在 C# 中能够做到的属性。
今天下午我起草了一份初稿,它允许您创建支持字段并指定它们的访问器,或者拥有没有支持字段的纯访问器。随着代码的发展,我将更新我的答案,并在我将其作为可以作为 composer 包导入的状态时提供一个链接。
为简单起见,我将功能创建为 PHP 特征,因此您可以将其放入所需的任何类中,而不必扩展基类。最终,我希望扩展此功能,以区分对属性的外部公共调用和受保护/私有调用。
这是 trait 本身的代码:
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; });
【讨论】:
这是 PHP ;你不需要设置
class MyClass {
public $ID;
}
$object = new MyClass();
$object->ID = 'foo';
echo $object->ID;
会起作用
【讨论】: