Brandon Williams
@rocketeerbkw
http://rocketeerbkw.github.io/slides/north-texas-drupal/developing-for-d8-isnt-hard/
Stop calling Drupal 8 hard!
This "marketing" is turning away people before they get a chance to see to see for themselves.
You'll recognize major Drupal concepts.
You won't recognize the boilerplate code.
There are some new things to get familiar with too.
function ntd_block_info() { $blocks = array(); $blocks['ntd_block_1'] = array( 'info' => 'NTD Block 1', ); return $blocks; } function ntd_block_view($delta) { $block = array(); switch ($delta) { case 'ntd_block_1'; $block['subject'] = t('Block 1'); $block['content'] = t('Content!'); } return $block; } function ntd_block_configure() {} function ntd_block_save() {}
namespace Drupal\ntd\Plugin\Block; use Drupal\Core\Block\BlockBase; /** * @Block( * id = "ntd_block_1", * admin_label = @Translation("Module Block 1") * ) */ class Block1 extends BlockBase { public function build() { return array( '#markup' => t('Content!'); ); } public function blockForm() {} public function blockSubmit() {} public function blockAccess() {} public function defaultConfiguration() {} }
... are small pieces of functionality that are swappable.
namespace Drupal\user\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
/**
* @FieldFormatter(
* id = "author",
* label = @Translation("Author"),
* description = @Translation("Display the referenced author user entity."),
* field_types = {
* "entity_reference"
* }
* )
*/
class AuthorFormatter extends FormatterBase {
public function viewElements(FieldItemListInterface $items) {}
public static function isApplicable(FieldDefinitionInterface $field_definition) {}
}
namespace Drupal\user\Plugin\Validation\Constraint;
use Symfony\Component\Validator\Constraint;
/**
* Checks if a user's email address is unique on the site.
*
* @Plugin(
* id = "UserMailUnique",
* label = @Translation("User email unique", context = "Validation")
* )
*/
class UserMailUnique extends Constraint {
public $message = 'The email address %value is already taken.';
public function validatedBy() {}
}
function ntd_boot() {
// Do stuff on every page load
}
function ntd_init() {
// Do stuff on every non-cached page load
}
services:
ntd.subscriber:
class: Drupal\ntd\NTDSubscriber
tags:
- { name: 'event_subscriber' }
namespace Drupal\ntd;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class NTDSubscriber implements EventSubscriberInterface {
public function onLoad(GetResponseEvent $event) {
// Do stuff on each page load
}
static function getSubscribedEvents() {
$events[KernelEvents::REQUEST][] = array('onLoad');
return $events;
}
}
From core.api.php
A human friendly data serialization standard for all programming languages.
Replacement for Drupal Arrays of Doom ™. Safer(ish) than moving PHP around.
$view = new view();
$view->name = 'test';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'node';
$view->human_name = 'Test';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Test';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['pager']['options']['items_per_page'] = '10';
$handler->display->display_options['style_plugin'] = 'default';
$handler->display->display_options['row_plugin'] = 'node';
/* Field: Content: Title */
$handler->display->display_options['fields']['title']['id'] = 'title';
$handler->display->display_options['fields']['title']['table'] = 'node';
$handler->display->display_options['fields']['title']['field'] = 'title';
$handler->display->display_options['fields']['title']['label'] = '';
$handler->display->display_options['fields']['title']['alter']['word_boundary'] = FALSE;
$handler->display->display_options['fields']['title']['alter']['ellipsis'] = FALSE;
/* Sort criterion: Content: Post date */
$handler->display->display_options['sorts']['created']['id'] = 'created';
$handler->display->display_options['sorts']['created']['table'] = 'node';
$handler->display->display_options['sorts']['created']['field'] = 'created';
$handler->display->display_options['sorts']['created']['order'] = 'DESC';
/* Filter criterion: Content: Published */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'node';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = 1;
$handler->display->display_options['filters']['status']['group'] = 1;
$handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page');
$handler->display->display_options['path'] = 'test';
uuid: 557e1a08-e34c-488a-8600-c77c496509fb
langcode: en
status: true
dependencies:
module:
- node
- user
id: test
label: Test
module: views
description: ''
tag: ''
base_table: node
base_field: nid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: perm
options:
perm: 'access content'
cache:
type: none
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: false
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: full
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous: '‹ previous'
next: 'next ›'
first: '« first'
last: 'last »'
quantity: 9
style:
type: default
row:
type: 'entity:node'
options:
build_mode: teaser
links: true
view_mode: teaser
rendering_language: translation_language_renderer
fields:
title:
id: title
table: node_field_data
field: title
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
link_to_node: 1
relationship: none
group_type: group
admin_label: ''
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
filters:
status:
value: true
table: node_field_data
field: status
provider: node
id: status
expose:
operator: ''
group: 1
sorts:
created:
id: created
table: node_field_data
field: created
order: DESC
relationship: none
group_type: group
admin_label: ''
exposed: false
expose:
label: ''
granularity: second
title: Test
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
field_langcode: '***LANGUAGE_language_content***'
field_langcode_add_to_query: null
path: test
ntd.routing.yml
ntd.dashboard
path: '/ntd/dashboard'
defaults:
_content: '\Drupal\ntd\Controller\DashboardController::dashboard'
_title: 'Dashboard'
requirements:
_permission: 'view ntd dashboard'
namespace Drupal\ntd\Controller;
Class DashboardController {
public function dashboard() {
return array(
'#markup' => t('Your Dashboard'),
);
}
}
books.links.tasks.yml
book.admin:
route_name: book.admin
title: 'Books'
base_route: system.admin_content
book.admin.list:
route_name: book.admin
title: 'List'
parent_id: book.admin
book.settings:
route_name: book.settings
title: 'Settings'
parent_id: book.admin
weight: 8
menu.links.action.yml
menu.menu_add:
route_name: menu.menu_add
title: 'Add menu'
appears_on:
- menu.overview_page
menu.links.contextual.yml
menu.edit:
title: 'Edit menu'
route_name: 'menu.menu_edit'
group: menu
book.links.menu.yml
book.render:
title: 'Books'
route_name: book.render
hidden: 1
function ntd_form($form, &$form_state) { $form['ntd_name'] = array( '#type' => 'textfield', '#title' => t('Name'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return system_settings_form($form); }
namespace Drupal\ntd\Form; use Drupal\Core\Form\ConfigFormBase; class NTDForm extends ConfigFormBase { public function getFormID() { return 'ntd.settings'; } public function buildForm(array $form, array &$form_state) { $form['ntd_name'] = array( '#type' => 'textfield', '#title' => t('Name'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return parent::buildForm($form, $form_state); } public function submitForm(array &$form, &$form_state) { // Set Config API stuff here parent::submitForm($form, $form_state); } }
variable_get('ntd_best_meetup', FALSE);
variable_set('ntd_best_meetup', TRUE);
best_meetup: n
organizers:
- David Hahn
- You!
$config = \Drupal::config('ntd.config');
$config->get('best_meetup'); // FALSE
Write Config
$config = \Drupal::service('config.factory')->getEditable('ntd.config');
$config->set('best_meetup', TRUE);
$config->save(); // Don't forget this!