30 Awesome Drupal 8 API Functions You Should Already Know

Created by Fredric Mitchell / @fredricmitchell

http://bit.ly/d8func-austin

Assumptions

  1. Show Me the Code!
  2. Written something custom (familiar with PHP)
  3. You like using APIs
  4. Drupal as framework
  5. KDS: http://bit.ly/p2-kds

Quick Intro

Paid Gig

Senior Developer at Phase2 Technology

Quick Intro

Passions

Drupal, DRY / KISS, Strat. Comm., Graphic Novels

Disclaimer! Disclaimer!

In D7, "API functions" == Common procedural functions

In D8, "API functions" == Common class methods

Some cases, procedurals are wrappers for methods

Then, and now

Additional Disclaimer! Disclaimer!

All recommendations are based on D8 as of June 3, 2014

Things may (and probably will) change

Strings

Print stuff.

String::checkPlain()

D7: check_plain()

Wrapper for htmlspecialchars with UTF-8 encoding

Still in bootstrap
use Drupal\Component\Utility\String;

String::placeholder()

D7: drupal_placeholder()

Wrap <em> around String:checkPlain()

t()

translate, sanitize

                            
$text = t(“@name's blog”, array('@name' => $value))
// Note:
@name (String::checkPlain())
vs. %name (String::placeholder())
vs. !name
                            
                        

l()

internal, external url

                            
$link = l(t('Link text'), 'node/34', array(
    'attributes' => array(
        'class' => array('about-link'),
    )
));
// Note: automatic alias replacement via url()
                            
                        

Rendering

Make stuff pretty.

drupal_render()

given render array, return HTML

                            
$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);
                            
                        

D8: drupal_render() is EVERYTHING!

Bye-bye theme()

_theme() is an internal function

#type defined in hook_element_info

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);
                            
                        

Nodes

Store content, data.

Wait...what!??! Hello? Entities!

Everything is entities now, right?

Yes. I was just getting there.

entity_load_multiple()

D7: node_load_multiple()

load nodes from db

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 EntityDatabaseStorage class

entity_load_multiple()

                            
$nodes = entity_load_multiple('node', $nids = array());

// Simpler
use \Drupal\node\Entity\Node;
$node = Node::load(1);
$nodes = Node::loadMultiple(array(1, 2, 3));
                            
                        

entity_view_multiple()

D7: node_view_multiple()

a render array of many nodes

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

entity_view_multiple()

                            
                                $nodes = entity_view_multiple($nodes);
                            
                        

entity_create()

D7: node_save()

save a node to db

node_save() is gone

entity_create wraps around $controller->create()

$controller is the StorageController for the entity

The storage controller is likely EntityDatabaseStorage class

entity_create()

                            
// Create a new forum instance.
$node = entity_create('node', array('otherValue' => 'foo'));

// Simpler
$node = Node::create(array('title' => 'My title'));

// Save entity to the database.
$node->save();
// Note: nothing is returned
                            
                        

Menus

Allow users to navigate to content, data.

module.routing.yml

D7: hook_menu()

define menu items and callbacks

D7

                            
function mymodule_menu() {
    $items['abc/def'] = array(
        'page callback' => 'mymodule_abc_view',
    );
    return $items;
}

function mymodule_abc_view($ghi = 0, $jkl = '') {
    // ...
}
                            
                        

module.routing.yml

D8

                            
mymodule.add_page:
    path: 'abc/def'
    defaults:
        _content: '\Drupal\mymodule\Controller\MyModuleController::addPage'
        _title: 'My Module'
    requirements:
        _permission: 'administer mymodule foobar'
                            
                        

$request()->attributes->get()

D7: menu_get_item()

get a router item

Uses the new routing system from Symfony

                            
$request = \Drupal::request();
$route = $request()->attributes->get(RouteObjectInterface::ROUTE_OBJECT);
                            
                        

$request()->attributes->get()

D7: menu_get_object()

load an object from router item

                            
$request = \Drupal::request();
$node = $request()->attributes->get('node');
$type = $node->type;
// Note: Use instead of arg()
                            
                        

As of 6 hours ago: https://drupal.org/node/2238217

\Drupal::routeMatch() service wrapper

menu_tree_page_data()

get data for menu tree

                            
                                $tree = menu_tree_page_data('main-menu');
                            
                        

menu_tree_output()

return a menu tree render array

                            
// Build a HTML menu
$tree = menu_tree_page_data('main-menu');
$menu = menu_tree_output($tree, 1);
return drupal_render($menu);
                            
                        

Taxonomy

Categorize content, data.

entity_load('taxonomy_vocabulary', 'forums')

D7: taxonomy_vocabulary_machine_name_load()

get vocabulary by machine name

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();
                            
                        

taxonomy_get_tree()

create hierarchy from vocab

                            
// 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;
}
                            
                        

Fields

Organize content, data at various pivot points.

$fieldInfo->getField()

D7: field_info_field()

return field data

Wraps around entity_load('field_config', ...)

                            
// Get info a field name.
$fieldInfo = \Drupal\field\Field::fieldInfo();
$fieldInfo->getField($entity_type, $field_name);
                            
                        

\Drupal::service('field.info'); (bonus)

$fieldInfo->getInstance()

D7: field_info_instance()

return field instance data

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');
                            
                        

entity_create('field_config', $values)

D7: field_create_field()

creates a field

The field configuration (field_config) is now an entity type

entity_create() invokes the create method of the EntityStorageBase (abstract)

The field_config maps to class FieldConfig and uses FieldConfigStorage

All other methods are in \Drupal\field\Entity\FieldConfig

field_create_field()

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);
                            
                        

entity_create('field_config', $values)

D8

                            
$field = entity_create('field_config', array(
    'name' => 'field_description',
    'entity_type' => 'taxonomy_term',
    'type' => 'text',
));
$field->save();
                            
                        

entity_create(
'field_instance_config', $values)

D7: field_create_instance()

create instance of field, binding it to a bundle

The field instance configuration (field_instance_config) is now an entity type

entity_create() invokes the create method of the EntityStorageBase (abstract)

The field_instance_config maps to class FieldInstanceConfig and uses FieldInstanceConfigStorage

All other methods are in \Drupal\field\Entity\FieldInstanceConfig

field_create_instance()

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);
                            
                        

entity_create(
'field_instance_config', $values)

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();
                            
                        

save()

D7: field_update_field()

D7: field_update_instance()

update field, field instance configs

                            
// 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();
                            
                        

Alters

Change the assumptions.

ModuleHandler::alter()

D7: drupal_alter()

passes variables to be changed

                            
$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.
                            
                        

hook_form_alter()

change a form before rendered

                            
function mymodule_form_alter(&$form, &$form_state) {
    $form['new_checkbox'] = array(
        '#type' => 'checkbox',
        '#title' => t ('Subscribe'),
    );
);
                            
                        

hook_form_FORM_ID_alter()

change a specific form by FORM ID before rendered

getFormId() method defines id to alter

hook_form_FORM_ID_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';
    }
}
                            
                        

hook_form_FORM_ID_alter()

                            
function mymodule_form_example_form_alter() {
    ...
);
                            
                        

More Info on Form API

https://drupal.org/node/2117411

Hooks

Engage other processes

moduleHandler::invokeAll()

D7: module_invoke_all()

Invoke the hooks

                            
\Drupal::moduleHandler->invokeAll($hook, $args);
                            
                        

moduleHandler
::getImplementations()

D7: module_implements()

Check a module invokes the hook

                            
\Drupal::moduleHandler->getImplementations($hook);
                            
                        

URLs

Grab the $_GET

UrlHelper::filterQueryParameters()

D7: drupal_get_query_parameters()

process url query

                            
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
                            
                        

Paths

Where am I?

drupal_get_path()

returns path to a system item

                            
// Path to a file
$path = drupal_get_path('theme', 'mytheme') . '/mycustom.js';
                            
                        

User

Who am I?

D7: global $user

User

Who am I?

D8: \Drupal::currentUser()

https://drupal.org/node/2032447

User

Who am I?

                            
$account = \Drupal::currentUser();
if ($account->id() == 1) {
    return "Hiya, boss!";
}
// $account is not an actual User object, but UserSession object
// Extends AccountInterface class
                            
                        

moduleHandler->loadInclude()

D7: module_load_include()

loads a module include file

                        
// Load node.admin.inc from the node module.
\Drupal::moduleHandler->loadInclude('node', 'inc', 'node.admin');
                        
                    

Querying Entities

Join ALL the tables!

\Drupal::entityQuery()

D7: EntityFieldQuery

search a single entity

D7: EntityFieldQuery

                            
// 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

\Drupal::entityQuery()

                            
$query = \Drupal::entityQuery('taxonomy_term')
    ->condition('tid', $term->id())
    ->condition('vid', $term->bundle())
    ->range(0, 1)
    ->count()
    ->execute();
                            
                        

https://drupal.org/node/1827278

Was that 30?

Kind of didn't feel like it.

What about functions completely removed?

#attached

D7: drupal_add_js, drupal_add_css, drupal_add_library

Gone!

https://drupal.org/node/2169605

#attached

                            
// 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')),
);
                            
                        

1 - 10

  • t()
  • String::checkPlain()
  • String::placeholder()
  • l()
  • drupal_render()
  • node_load_multiple() entity_load_multiple()
  • node_view_multiple() entity_view_multiple()
  • node_save() entity_create()
  • hook_menu() module.routing.yml
  • menu_get_item() $request()->attributes->get()

11 - 20 17

  • menu_get_object() $request()->attributes->get()
  • menu_tree_page_data()
  • menu_tree_output()
  • taxonomy_get_tree()
  • taxonomy_vocabulary_machine_name_load() entity_load('taxonomy_vocabulary', 'forums')
  • field_info_field() $fieldInfo->getField()
  • field_info_instance() $fieldInfo->getInstance()
  • field_create_field() entity_create('field_config', $values)
  • field_create_instance() entity_create('field_instance_config', $values)
  • field_update_field() save()

18 - 28

  • field_update_instance() save()
  • drupal_alter() ModuleHandler::alter()
  • hook_form_alter()
  • hook_form_FORM_ID_alter()
  • moduleHandler::invokeAll()
  • moduleHandler::getImplementations()
  • drupal_get_query_parameters() UrlHelper::filterQueryParameters()
  • drupal_get_path()
  • module_load_include() moduleHandler->loadInclude()
  • EntityFieldQuery \Drupal::entityQuery()

So, it wasn't 30

Technically, no.

#attached could be a +3

drupal_add_js, drupal_add_css, drupal_add_library

More Bonus!

arg() is gone!!!

https://drupal.org/node/2274705

More Bonus!

\Drupal

Static service container wrapper

A unified global accessor to arbitrary services

Ex: hasRequest(), httpClient(), queue()

What's Next?

Contribute to Examples: https://drupal.org/project/examples

Read docs: https://drupal.org/developing/api/8

Scaffold: https://github.com/hechoendrupal/DrupalAppConsole

What's Next (at Drupalcon)?

Questions?

By Fredric Mitchell / @fredricmitchell

Slides: http://bit.ly/d8func-austin

Slides Repo: https://github.com/fmitchell/d8apifunc-austin