Last active 1 month ago

Drupal 11 Context Raw
1# Drupal 11 Content Management System
2
3## Introduction
4
5Drupal 11 is a modern, enterprise-grade content management framework built on PHP 8.3+ and Symfony 7 components. Unlike Drupal 7's procedural architecture, Drupal 11 utilizes a fully Object-Oriented Programming (OOP) architecture, leveraging a Dependency Injection Container, Composer for package management, and a plugin-based system for extensibility.
6
7At its core, Drupal 11 treats content as **Entities** (typed objects). It separates configuration (YAML-based) from content (Database-based). The system relies on PSR-4 autoloading, namespaced classes, and event subscribers. While legacy hooks exist, Drupal 11 introduces **Hook Attributes** and emphasizes Event Subscribers. Output is handled via the Twig templating engine, and routing is defined via YAML files mapping paths to Controller classes.
8
9## APIs and Key Functions
10
11### Entity API - Content CRUD Operations
12
13The Entity API is the primary method for interacting with data. Nodes, Users, Terms, and custom entities are all instances of classes implementing `EntityInterface`. Direct database access for content is discouraged.
14
15```php
16use Drupal\node\Entity\Node;
17use Drupal\Core\File\FileSystemInterface;
18
19// Create a new article node
20$node = Node::create([
21 'type' => 'article',
22 'title' => 'Getting Started with Drupal 11',
23 'langcode' => 'en',
24 'uid' => 1, // Author ID
25 'status' => Node::PUBLISHED,
26 'body' => [
27 'value' => 'Drupal 11 is a powerful framework...',
28 'format' => 'full_html',
29 ],
30 // Entity reference (Taxonomy) uses target_id
31 'field_tags' => [
32 ['target_id' => 5],
33 ['target_id' => 8],
34 ],
35]);
36
37// Save the node
38$node->save();
39echo "Created node with ID: " . $node->id();
40
41// Load an existing node
42$node = Node::load(1);
43if ($node instanceof Node) {
44 // Access fields using Magic Getters or get()
45 echo $node->getTitle();
46 echo $node->body->value;
47 echo $node->get('body')->value; // more explicit
48
49 // Access Entity Reference fields
50 if (!$node->get('field_image')->isEmpty()) {
51 $entity = $node->field_image->entity;
52 $url = $entity->createFileUrl();
53 }
54}
55
56// Load multiple nodes
57$nids = [1, 2, 3, 4, 5];
58$nodes = Node::loadMultiple($nids);
59foreach ($nodes as $node) {
60 echo $node->label() . "\n";
61}
62
63// Update a node
64$node = Node::load(1);
65$node->setTitle('Updated Article Title');
66$node->set('body', ['value' => 'Updated content...', 'format' => 'basic_html']);
67$node->field_category[] = ['target_id' => 10]; // Append value
68$node->setNewRevision(TRUE);
69$node->revision_log = 'Updated article info';
70$node->save();
71
72// Delete a node
73$node = Node::load(1);
74$node->delete();
75
76// Delete multiple nodes (loading them first is best practice to trigger hooks)
77$nodes = Node::loadMultiple([5, 6, 7]);
78$storage_handler = \Drupal::entityTypeManager()->getStorage('node');
79$storage_handler->delete($nodes);
80
81// Get node by properties (using Entity Storage)
82$nodes = \Drupal::entityTypeManager()
83 ->getStorage('node')
84 ->loadByProperties(['title' => 'My Article', 'status' => 1]);
85$node = reset($nodes);
86```
87
88### Entity Query API - Complex Content Queries
89
90Replaces `EntityFieldQuery`. Used to find entity IDs based on field values or properties. Always uses fluent interfaces.
91
92```php
93// Basic node query
94$query = \Drupal::entityQuery('node')
95 ->condition('type', 'article')
96 ->condition('status', 1)
97 ->condition('field_category.entity.name', 'Tech') // Query referenced entity data
98 ->sort('created', 'DESC')
99 ->range(0, 10)
100 ->accessCheck(TRUE); // MANDATORY in D10/11
101
102$nids = $query->execute();
103$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
104
105// Complex conditions (AND/OR groups)
106$query = \Drupal::entityQuery('node')
107 ->condition('status', 1)
108 ->accessCheck(TRUE);
109
110$group = $query->orConditionGroup()
111 ->condition('field_price', 100, '>')
112 ->condition('field_stock', 0, '>');
113
114$query->condition($group);
115$result = $query->execute();
116
117// Date range query
118$query = \Drupal::entityQuery('node')
119 ->condition('field_date.value', ['2024-01-01', '2024-12-31'], 'BETWEEN')
120 ->accessCheck(TRUE)
121 ->execute();
122
123// Count results only
124$count = \Drupal::entityQuery('node')
125 ->condition('type', 'article')
126 ->accessCheck(TRUE)
127 ->count()
128 ->execute();
129```
130
131### Database API
132
133Used for non-entity data or performance-critical reporting. Access is typically handled via Dependency Injection (`@database` service), but static access exists for legacy support or scripts.
134
135```php
136use Drupal\Core\Database\Database;
137
138$connection = \Drupal::database();
139
140//