On Github fmitchell / d8apifuncnyccamp2014
Created by Fredric Mitchell / @fredricmitchell
http://brightplumbox.com/d8apifuncnyccamp2014/#/
Senior Developer at Phase2 Technology
Drupal, DRY / KISS, Strat. Comm., Graphic Novels
Wrapper for htmlspecialchars with UTF-8 encoding
Wrap <em> around String:checkPlain()
$text = t(“@name's blog”, array('@name' => $value))
// Note:
@name (String::checkPlain())
vs. %name (String::placeholder())
vs. !name
$link = l(t('Link text'), 'node/34', array(
'attributes' => array(
'class' => array('about-link'),
)
));
// Note: automatic alias replacement via url()
$render = array(
'first_para' => array(
'#type' => 'markup',
'#markup' => 'A first paragraph',
),
'second_para' => array(
array('first item', 'second item', 'third item'),
'#theme' => 'item_list',
),
);
return drupal_render($render);
_theme() is an internal function
D7
// Theme a table with header and row data.
$markup = theme('table', array(
'header' => $header,
'rows' => $rows,
'attributes' => array('id' => 'my-module-table')
));
// Render a pager.
$markup .= theme('pager');
D8
$table = array(
'#type' => 'table',
'#header' => $header,
'#rows' => $rows,
'#attributes' => array('id' => 'my-module-table'),
);
$markup = drupal_render($table);
// Pager is not an element type, use #theme directly.
$pager = array('#theme' => 'pager');
$markup .= drupal_render($pager);
Yes. I was just getting there.
node_load_multiple wraps around entity_load_multiple
entity_load_multiple wraps around $controller->loadMultiple()
$controller is the StorageController for the entity
The storage controller is likely DatabaseStorageController class
$nodes = entity_load_multiple('node', $nids = array())
// Note: Cached
node_view_multiple wraps around entity_view_multiple
entity_view_multiple wraps around $render_controller->viewMultiple()
$render_controller is the getViewBuilder for the entity
The view builder controller is likely EntityViewBuilder class
$nodes = entity_view_multiple($nodes);
node_save() is gone
entity_create wraps around $controller->create()
$controller is the StorageController for the entity
The storage controller is likely DatabaseStorageController class
// Create a new forum instance.
$node = entity_create('node', array('otherValue' => 'foo'));
// Save entity to the database.
$node->save();
// Note: nothing is returned
D7
function mymodule_menu() {
$items['abc/def'] = array(
'page callback' => 'mymodule_abc_view',
);
return $items;
}
function mymodule_abc_view($ghi = 0, $jkl = '') {
// ...
}
D8
mymodule.add_page:
path: 'abc/def'
defaults:
_content: '\Drupal\mymodule\Controller\MyModuleController::addPage'
_title: 'My Module'
requirements:
_permission: 'administer mymodule foobar'
Uses the new routing system from Symfony
$request = \Drupal::request();
$route = $request()->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
$request = \Drupal::request();
$node = $request()->attributes->get('node');
$type = $node->type;
// Note: Use instead of arg()
Discussion: https://drupal.org/node/2124749
Possibly have $request, $route_match, and $context_container as separate objects.
$tree = menu_tree_page_data('main-menu');
// Build a HTML menu
$tree = menu_tree_page_data('main-menu');
$menu = menu_tree_output($tree, 1);
return drupal_render($menu);
D7
// Get a taxonomy object.
$vocabulary = taxonomy_vocabulary_machine_name_load('forums');
$options[$vocabulary->vid] = $vocabulary->name;
D8
// Get a taxonomy object.
$vocabulary = entity_load('taxonomy_vocabulary', 'forums');
$options[$vocabulary->id()] = $vocabulary->label();
// Get a taxonomy object.
$v = entity_load('taxonomy_vocabulary', 'forums');
// Build an array of taxonomy terms.
$terms = taxonomy_get_tree($v->id());
foreach ($terms as $term) {
$options[$term->tid] = $term->name;
}
Wraps around entity_load('field_config', ...)
// Get info a field name.
$fieldInfo = \Drupal\field\Field::fieldInfo();
$fieldInfo->getField($entity_type, $field_name);
Wraps around entity_load_multiple('field_instance_config', ...)
// Get info on field name.
$fieldInfo = \Drupal\field\Field::fieldInfo();
// Get info on instance of field name from a bundle.
$fieldInfo->getInstance('node', 'article', 'field_name');
The field configuration (field_config) is now an entity type
entity_create() invokes the create method of the StorageController
The field_config entity uses FieldConfigStorageController
All other methods are in \Drupal\field\Entity\FieldConfig
D7
// Note: Requires proper field / instance data array which you can get from a features export.
$field_bases = array();
// Exported field_base: 'field_sc_html'
$field_bases['field_sc_html'] = array(
'active' => 1,
'cardinality' => 1,
'deleted' => 0,
'entity_types' => array(),
'field_name' => 'field_sc_html',
'foreign keys' => array(
'format' => array(
'columns' => array(
'format' => 'format',
),
'table' => 'filter_format',
),
),
'indexes' => array(
'format' => array(
0 => 'format',
),
),
'locked' => 0,
'module' => 'text',
'settings' => array(),
'translatable' => 0,
'type' => 'text_long',
);
field_create_field($field_bases);
D8
$field = entity_create('field_config', array(
'name' => 'field_description',
'entity_type' => 'taxonomy_term',
'type' => 'text',
));
$field->save();
The field instance configuration (field_instance_config) is now an entity type
entity_create() invokes the create method of the StorageController
The field_instance_config entity uses FieldInstanceConfigStorageController
All other methods are in \Drupal\field\Entity\FieldInstanceConfig
D7
// Note: Requires proper field / instance data array which you can get from a features export.
$field_instances = array();
// Exported field_instance: 'bean-field_sc_html'
$field_instances['bean-field_sc_html'] = array(
'bundle' => 'oms_sidebar_content',
'default_value' => NULL,
'deleted' => 0,
'description' => '',
'display' => array(
'default' => array(
'label' => 'above',
'settings' => array(),
'type' => 'hidden',
'weight' => 0,
),
),
'entity_type' => 'bean',
'field_name' => 'field_sc_html',
'label' => 'HTML',
'required' => 0,
'settings' => array(
'text_processing' => 1,
'user_register_form' => FALSE,
),
'widget' => array(
'active' => 1,
'module' => 'text',
'settings' => array(
'rows' => 5,
),
'type' => 'text_textarea',
'weight' => 2,
),
);
field_create_instance($field_instances);
D8
$field_instance = entity_create('field_instance_config', array(
'field_name' => 'field_description',
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'label' => 'Custom tag description',
));
$field_instance->save();
D7
function mymodule_install_fields($fields, $instance_fields, $type = 'node', $bundle) {
foreach ($fields as $field) {
// Create the field if it doesn't exist.
if (!field_info_field($field['field_name'])) {
field_create_field($field);
}
}
unset($field);
foreach ($instance_fields as $field) {
if (!field_info_instance($type, $field['field_name'], $bundle)) {
field_create_instance($field);
}
}
}
// Updating field.
$field->cardinality = 2;
$field->save();
// Deleting field.
entity_load('field_config', 'field_name')->delete();
// Deleting instance.
entity_load('field_instance_config', 'field_instance_name')->delete();
$data = array(
'key1' => 'value1',
'key2' => 'value2',
);
// Call all modules implementing hook_my_data_alter
\Drupal::moduleHandler()->alter('my_data', $data);
// Note: Use sparingly. hook_theme() is preferred for overriding styles.
function mymodule_form_alter(&$form, &$form_state) {
$form['new_checkbox'] = array(
'#type' => 'checkbox',
'#title' => t ('Subscribe'),
);
);
getFormId() method defines id to alter
/**
* @file
* Contains \Drupal\example\Form\ExampleForm.
*/
namespace Drupal\example\Form;
use Drupal\Core\Form\FormBase;
/**
* Implements an example form.
*/
class ExampleForm extends FormBase {
/**
* {@inheritdoc}.
*/
public function getFormId() {
return 'example_form';
}
}
function mymodule_form_example_form_alter() {
...
);
https://drupal.org/node/2117411
\Drupal::moduleHandler->invokeAll($hook, $args);
\Drupal::moduleHandler->getImplementations($hook);
use Drupal\Component\Utility\UrlHelper;
// URL: http://mysite.com?text=foo&date=2013-09-14
$url = \Drupal::request()->query->all(); // May not be best way
$param = UrlHelper::filterQueryParameters($url);
// Values
// $param['text'] = foo
// $param['date'] = 2013-09-14
// Path to a file
$path = drupal_get_path('theme', 'mytheme') . '/mycustom.js';
D7: global $user
D8: \Drupal::currentUser()
https://drupal.org/node/2032447
$account = \Drupal::currentUser();
if ($account->id() == 1) {
return "Hiya, boss!";
}
// $account is not an actual User object, but UserSession object
// Extends AccountInterface class
// Load node.admin.inc from the node module.
\Drupal::moduleHandler->loadInclude('node', 'inc', 'node.admin');
// Query articles
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'article')
->propertyCondition('status', 1);
$result = $query->execute();
$nids = array_keys($result['node']);
$nodes = node_load_multiple($nids);
EFQ presentation at http://bit.ly/top10efq
$query = \Drupal::entityQuery('taxonomy_term')
->condition('tid', $term->id())
->condition('vid', $term->bundle())
->range(0, 1)
->count()
->execute();
https://drupal.org/node/1827278
What about functions completely removed?
Gone!
https://drupal.org/node/2169605
// within CKEditor
public function settingsForm(array $form, array &$form_state, EditorEntity $editor) {
$ckeditor_settings_toolbar = array(
'#theme' => 'ckeditor_settings_toolbar',
'#editor' => $editor,
'#plugins' => $this->ckeditorPluginManager->getButtons(),
);
$form['toolbar'] = array(
'#type' => 'container',
'#attached' => array(
'library' => array('ckeditor/drupal.ckeditor.admin'),
'js' => array(
array(
'type' => 'setting',
'data' => array('ckeditor' => array(
'toolbarAdmin' => drupal_render($ckeditor_settings_toolbar),
)),
)
),
),
'#attributes' => array('class' => array('ckeditor-toolbar-configuration')),
);
Technically, no.
#attached could be a +3
drupal_add_js, drupal_add_css, drupal_add_library
Contribute to Examples: https://drupal.org/project/examples
Read docs: https://drupal.org/developing/api/8
Scaffold: https://github.com/hechoendrupal/DrupalAppConsole
Slides: http://brightplumbox.com/d8apifuncnyccamp2014/#/
Slides Repo: https://github.com/fmitchell/d8apifuncnyccamp2014