背景信息:我试图操作列表类型文本字段的可用选项,具体取决于主机包:
function wtbase_options_list_alter(array &$options, array $context) {
$fieldDefinition = $context['fieldDefinition'];
if ($fieldDefinition->getName() == 'field_aos_cell' && $fieldDefinition->bundle() != 'link') {
foreach ($options as $key => $value) {
if ($key == 'link-horizontally-opposing') {
unset($options[$key]);
}
}
}
}$fieldDefinition->bundle部分非常令人困惑。似乎有一个变量$fieldDefinition->bundle (包含预期的包名link)和一个函数$fieldDefinition->bundle() (包含field_config)。但是我无法访问变量bundle,因为这与Cannot access protected property Drupal\field\Entity\FieldConfig::$bundle崩溃了。
经过深入研究,我找到了FieldConfigBase::getTargetBundle(),它确实返回了预期的结果,并且没有崩溃(目前为止)。
这就引出了两个问题:
$bundle、bundle()和getTargetBundle()之间有什么区别,我应该使用哪一种?我更喜欢使用变量,因为它们在Xdebug中是可见的,而函数不是。
更普遍的观点是,在什么时候使用函数和什么时候使用变量有一些指导原则吗?在上面的示例中,Xdebug打印了相同的奇怪结果,例如entity_type与entityTypeId、getEntityType()与getEntityTypeId()。
--
问题1的更新和澄清:
我知道成员属性和成员函数之间的技术区别。但是,我深感困惑的是,属性$bundle和完全相同名称的函数bundle()正在从完全不同的实体/上下文返回值。在我的示例中,$fieldDefinition->bundle返回一个段落包名link,而$fieldDefinition->bundle()似乎从FieldConfig返回包名。我知道这在技术上是可能的..。但是为什么会有人写这样的代码呢?我还没有在Drupal中的任何其他地方体验过这种行为,通常$entity->bundle和$entity->bundle()返回相同的结果。
发布于 2019-09-23 11:04:14
bundle是对象的属性。它是储存价值的地方。属性可以通过以下三种方式之一分配:
public:这些属性可以直接在对象上设置或读取。例如:$object->key = 'value';$value = $object->key;private:这些只能通过类本身的方法(函数)访问。其他任何东西都无法访问它。这可以用于对要存储在属性中的数据类型强制执行规则。可以运行检查以确保它是允许的数据类型。protected:这些类似于私有属性,但是如果类扩展了类,则扩展类可以访问该属性。如果属性是私有的,扩展类将无法访问它。您需要理解的一件事是,$node->bundle和$node->bundle()是不一样的。第一个是属性,另一个是方法。这应该有助于理解,作为一个(非真实的)例子:
class Node {
protected $bundle;
public function bundle() {
return $this->bundle;
}
}上述类具有属性$bundle和方法(函数) bundle()。该方法返回存储在属性中的值。
看看您所看到的错误:Cannot access protected property Drupal\field\Entity\FieldConfig::$bundle。这是因为您试图访问$bundle属性,但它是受保护的,这意味着您不能从类之外访问它。
要获得节点的包,需要调用节点上的bundle()方法,这将为您提供包类型。这是你关于使用哪一个问题的答案。
更普遍的观点是,在什么时候使用函数和什么时候使用变量有一些指导原则吗?
通常认为最好的做法是不提供对对象的属性的直接访问,而是在对象上创建setter和getter方法(函数)来设置和检索属性值。这样你就可以说,强制执行一种模式:
class Example {
protected $username
public function setUsername($username) {
if (!is_string($username)) {
throw new \Exception('Username must be a string');
}
elseif (!preg_match('/^[a-zA-Z0-9_-]{3,12}$/', $username)) {
throw new \Exception('Username must be between 3 and 12 characters, and may contain only alphanumerics, underscores or hyphens');
}
$this->username = $username;
}
public function getUsername() {
return $this->username;
}
}以上强制表示用户名既是一个字符串,也是正确的长度,并且只包含允许的字符。
编辑:来自Leigh的其他评论:
避免直接访问属性的另一个原因是当您有多个值时。例如,如果在节点上有一个字段"my_field“,如果使用$ node ->my_ field ->value,则该字段具有多个值,则只返回1个值。
https://drupal.stackexchange.com/questions/286641
复制相似问题