“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
首先需要明白Drupal的字段对象是一个类数组对象,又叫做字段条目列表对象,其基类如下:
\Drupal\Core\Field\FieldItemList
可以用数组方式来访问其中的每个字段条目对象(数组中的元素即为条目对象),条目对象基类如下:
\Drupal\Core\Field\FieldItemBase
换句话说,前者(字段条目列表对象)通过如下两种方式得到后者(条目对象):
$entity->fieldName[0]
$entity->fieldName->get(0)
条目对象拥有一个或多个属性对象,通过get(属性名)来访问属性对象,属性对象包装着标量类型数据,也可以直接通过属性名访问,但二者有区别,见注释:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(46);
$entity->title[0]->value; //得到属性标量值
$entity->title[0]->get('value'); //得到属性对象,而不是标量值
由于有PHP魔术方法的帮助,使得实体字段对象赋值和取值非常方便,但这种太过灵活的用法也让新手难以驾驭,本文系统性的进行解释。
赋值操作:
为单一属性赋值:
$entity->fieldName[0]-> propertyName=$value;
$entity->fieldName->get(0) -> propertyName =$value;
这是标准的、完整的操作演示,这里$value应是标量数据
含义是:向实体的某个字段的某个下标字段条目的某个属性赋值,可以省略下标表示,此时则表示为第一个条目对象的某属性赋值
这里以节点实体类型下的文章内容类型为例来说明:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(47);
$entity->body[0]->value='正文';
$entity->body[0]->summary='摘要';
$entity->save();
省略下标写法如下:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(47);
$entity->body->value='正文';
$entity->body->summary='摘要';
$entity->save();
以上两段代码效果一样
为所有属性赋值:
也可以一次性为某个字段的某个下标字段条目的所有属性赋值:
$entity->fieldName[0]=$value;
$entity->fieldName->get(0)=$value;
同样可以省略下标变为:
$entity->fieldName=$value;
同样的,省略时默认表示第一个,示例如下:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(47);
$entity->body=['value'=>'正文','summary'=>'摘要'];
$entity->save();
此时$value是一个数组,键名应为属性名,键值为对应的值。
但$value也可以不是数组而是一个标量值,示例如下:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(47);
$entity->body='正文6';
$entity->save();
这表示在为字段对象的第一个条目对象的主属性赋值,哪一个属性为主属性由字段条目对象的mainPropertyName()方法决定,大多数字段的主属性名为value,但并非全部,比如引用字段的主属性名就是target_id,链接字段为uri,所以主属性应以mainPropertyName()方法返回值为准,为主属性赋值时,主属性是可以省略的,但此时当条目对象还有其他属性时,它们将被清空,比如:
$entity->body='正文6';
将使得摘要属性等被清空。
在系统中许多字段的条目对象只有一个属性,“主属性”概念的出现,使得赋值操作不用明确写出属性名,变的简洁了,但这也是让新手疑惑的地方。
注意在读取时主属性则不能省略:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(46);
$entity->title="yunke";
echo $entity->title; //错误,php异常,主属性不能省略,试图读出字符串“yunke”,
echo $entity->title->value; //正确,应该明确写出主属性
见下文的取值操作。
取值操作:
取值操作不管是否主属性,均不能省略属性名,必须明确写出,以下写法是错误的:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(46);
echo $entity->title;
必须明确给出属性名(即便是主属性也不能省略),正确的写法是:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(46);
echo $entity->title->value;
注意这里的“$entity->title->value”是一个标量值,如果要得到属性对象需如下:
$entity->title[0]->get('value');
这种情况下注意这里的下标不能省略,否则调用的是条目列表对象上的”get”方法(得到条目对象),而不是条目对象上的”get”方法(得到属性对象)。
并不是所有字段类型的主属性都是“value”,比如link(链接字段类型)、和引用字段类型就不是,示例:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(46);
echo $entity->uid->target_id; //获取到的是目标实体id的原始值
从引用字段得到被引用的实体对象:
示例如下:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(46);
echo $entity->type->entity->label(); //输出节点内容类型的名字
echo $entity->uid->entity->name->value;//输出节点作者的名字
说明如下:
得到节点内容类型配置实体:$entity->type->entity
得到节点作者用户实体对象:$entity->uid->entity
其中将“entity”替换为“target_id”即得到目标实体原始的实体ID(标量数据类型)。
得到被引用实体后对其的赋值、取值操作同上。
从字段对象得到其所属的实体对象:
如下代码是成立的:
$entity=\Drupal::entityTypeManager()->getStorage("node")->load(46);
$entity->field_url[0]->getEntity()===$entity
$entity->field_url->getEntity()===$entity
但须注意:以上虽然都是调用getEntity()方法,但是是在不同对象上调用:
带下标:是从一个字段条目对象上取得所属实体;
不带下标:是从字段列表对象上取得所属实体;
是否省略下标有本质区别,但她们的返回值是完全相同的,均是所属的实体对象。
如何确定属性名:
当你在赋值、取值某字段条目对象时,如果不知道具体的属性名,那么可以先找到该字段对应的字段类型定义插件(可用yunke_help模块查看),查看其中的propertyDefinitions方法,比如文章内容类型下默认的body字段,对应的是带摘要的文本字段类型,则查看如下:
\Drupal\text\Plugin\Field\FieldType\TextWithSummaryItem::propertyDefinitions
我是云客,一个热爱Drupal,热爱编程的创业者(未来很美科技创始人),试图让更多人看到PHP的那些高山风景而尽己所能,所有原创内容会发布到我的个人网站“水滴间”,未来很美,一起向前
交流互动