Last active 1 month ago

jon's Avatar jon revised this gist 1 month ago. Go to revision

No changes

jon's Avatar jon revised this gist 1 month ago. Go to revision

1 file changed, 140 insertions

Drupal 11 Context (file created)

@@ -0,0 +1,140 @@
1 + # Drupal 11 Content Management System
2 +
3 + ## Introduction
4 +
5 + Drupal 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 +
7 + At 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 +
13 + The 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
16 + use Drupal\node\Entity\Node;
17 + use 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();
39 + echo "Created node with ID: " . $node->id();
40 +
41 + // Load an existing node
42 + $node = Node::load(1);
43 + if ($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);
59 + foreach ($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 +
90 + Replaces `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 +
133 + Used 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
136 + use Drupal\Core\Database\Database;
137 +
138 + $connection = \Drupal::database();
139 +
140 + //
Newer Older