jon revised this gist 1 month ago. Go to revision
No changes
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