logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动
16/10/2025, by Ivan

在实体中获取字段值相当简单,但有几种不同的方法可用。让我们看看在自定义代码中处理字段值的最佳方式。你可以随时在官方网站上查看有关使用字段的最新信息:

https://www.drupal.org/docs/8/api/entity-api/working-with-the-entity-api

本文将通过示例讲解如何操作字段值。

你无需死记字段的工作方式,可以随时回到此页面复习。随着时间的推移,你会越来越多地查阅官方文档,并逐渐意识到在 Drupal 中操作字段其实非常简单。同时,你也可以将此页加入书签,以便随时查阅。

操作节点(Node)

按 nid 加载节点:

$nid = 234; 
$node_storage = \Drupal::entityTypeManager()->getStorage('node');
$node = $node_storage->load($nid);

获取节点 ID:

$node->id();

获取节点或实体的 bundle:

$node->bundle();   
$entity->getType(); 

获取字段值:

$node->get('title')->value;           
$node->get('created')->value;      
$node->get('body')->value;          
$node->get('body')->summary;         
$node->get('field_foo')->value;     
$node->get('field_image')->target_id;

也可以使用简写方式获取值:

$node->title->value;
$node->created->value;
$node->body->value;
$node->body->summary;
$node->field_foo->value;
$node->field_image->target_id;

通过字段值加载特定节点:

$query = \Drupal::entityQuery('node')
  ->condition('type', 'article')
  ->condition('field_terms', 42);
$nids = $query->execute();
$nodes = $node_storage->loadMultiple($nids);
  
foreach ($nodes as $node) {
  print $node->title->value;
  $node->set('title', "New title for node");
  $node->save();
}

修改字段中的值:

$node->set('title', "New title");
$node->set('body', array(
'summary' => "Teaser",
'value' => "Long text",
'format' => 'basic_html',
));
$node->save();

对于只有一个值的字段,可以使用简写形式:

$node->title = 'New title';
$node->field_text = 'text';

获取多值字段的值:

$nids = \Drupal::entityQuery('node')->condition('type', 'album')->execute();
$nodes = Node::loadMultiple($nids);
 
$data = array();
foreach($nodes as $node) {
  $photo = array();
  foreach($node->get('field_image')->getValue() as $file){
    $fid = $file['target_id']; // 获取文件 fid
    $photo[] = \Drupal\file\Entity\File::load($fid)->getFileUri();
  }
 
  $data[] = array(
    'album_name' => $node->get('field_album_name')->getValue(),
    'place' => $node->get('field_place')->getValue(),
    'author' => $node->get('field_author')->getValue(),
    'photo' => $photo,
  );
}

操作文件字段(File Fields)

文件通常通过引用字段附加到其他实体。当我们访问这些字段时,可以获取文件 ID,然后根据该 ID 获取文件信息。

通过 ID 获取文件:

$fid = 42; 
$file_storage = \Drupal::entityTypeManager()->getStorage('file');
$file = $file_storage->load($fid);

从节点字段中获取文件对象:

$file = $node->field_image->entity;

获取文件对象的属性:

$file->getFileUri();   // "public://file123.jpg"
// 将 URI 转换为文件 URL:file_url_transform_relative(file_create_url($file->getFileUri()));   
// "/sites/default/files/public/file123.jpg"
$file->filename->value;   // "file123.jpg"
$file->filemime->value;   // "image/jpeg"
$file->filesize->value;   // 63518(字节)
$file->created->value;    // 1511206249(Unix 时间戳)
$file->changed->value;    // 1511234256(Unix 时间戳)
$file->id();

可以通过以下方式查看 file_managed 表中可用的属性值:

echo $file->uid->target_id;               // 1
echo $file->uid->value;                   // 无效!请使用 target_id。
echo $file->uid->entity->name->value;    
echo $file->uid->entity->timezone->value; // "Asia/Omsk"

操作实体引用字段(Entity Reference Fields)

可以从引用字段中获取多个值,并通过 foreach 遍历处理:

foreach ($node->field_my_entity_reference as $reference) {  
  print $reference->target_id;  
  print $reference->entity->title->value;  
}

修改多值实体引用字段:

$nids = [3,4,5,6];  
$node->set('field_my_entity_reference', $nids);
$node->save();

在原有引用字段中追加新值:

$nids = [3,4,5,6];   // 示例值
foreach ($nids as $nid) {
  $node->field_my_entity_reference[] = [
    'target_id' => $nid
  ];
}
$node->save();

比较字段的新旧值

FieldItemListInterface(每个字段背后的类)具有一个 equals() 方法:

/**
 * 实现 hook_entity_update().
 */
function mymodule_entity_update(\Drupal\Core\Entity\EntityInterface $entity) {
  // 确保实体包含该字段。
  if (!$entity->hasField('field_wikipage_access') || !isset($entity->original)) {
    return;
  }

  $new_values = $entity->get('field_wikipage_access');
  $old_values = $entity->original->get('field_wikipage_access');

  // 判断字段是否已更改
  if ($new_values->equals($old_values)) {
    return;  // 无变化,提前退出。
  }

  // 否则继续执行逻辑
}

操作段落(Paragraphs)

$my_paragraph = null;
  
foreach ($node->get('field_paragraph_reference') as $paragraph) {
  if ($paragraph->entity->getType() == 'your_paragraph_type') {  
    $my_paragraph = $paragraph->entity;
  }
}
  
if (!empty($my_paragraph)) {
  print $my_paragraph->field_somefield->value;
  
  print $my_paragraph->title->value;  // 无效!
} 
else {
  print "该节点没有此类型的段落。";
}

获取段落类型:

$my_paragraph->getType();

我们将在后续编写自定义模块(使用 hooks 和实体对象)时继续使用这些示例。