Drupal实体对象赋值、取值操作

yunke 提交于 周一, 09/13/2021 - 08:58

首先需要明白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的那些高山风景而尽己所能,所有原创内容会发布到我的个人网站“水滴间”,未来很美,一起向前

 

 

 

添加新评论

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。
请输入以上问题的答案,换一个问题请刷新,不区分大小写