SlideShare a Scribd company logo
Drupal 8 in action,
the route to the method
@juanolalla #DrupalCampEs
about.me/juanolalla
Juan Olalla
web developer focused on drupal
at @ideup (@gowex)

Motivation
I’ve recently been contributing to Drupal 8 core
and I want to share with you what I've learned
Wellcome to
Drupal 8 Routing
Goodbye to
hook_menu()
Goodbye to hook_menu() for routing
and for everything else...
Routing

Routes defined in routing.yml and controllers

Menu links

Defined in hook_default_menu_links()

Local actions

Plugins defined in local_actions.yml

Local tasks

Plugins defined in local_tasks.yml

Contextual links

Plugins defined in contextual_links.yml

Breadcrumbs

Implementing BreadcrumbBuilder plugins

Links can be related regardless of the path, managed by machine names.
Drupal 8 uses Symfony2 Routing
component
And also uses Symfony CMF
RoutingBundle for dynamic routing
What is a route?
A route is an object defined by
1. Path
2. Default values
3. Requirements
4. Options
5. Host
6. Schemes
7. Methods
ueSmoyCmoetRuigRue
s yfnopnnotnot;
$ot =nwRue
rue
e ot(
'acie{ot},/ pt
/rhv/mnh' / ah
ary'otolr = 'hwrhv',/ dfutvle
ra(cnrle' > soAcie) / eal aus
ary
ra(
'ot'= '09{}[-]2'
mnh > [-]4-09{},
'udmi'= 'w|'
sboan > wwm,
) / rqieet
, / eurmns
ary) / otos
ra(, / pin
'sboan.xml.o' / hs
{udmi}eapecm, / ot
ary) / shms
ra(, / cee
ary)/ mtos
ra( / ehd
)
;
The Routing component gets routes from
• PHP code:
• a RouteCollection object
• closures
• class annotations
• External files:
• YAML
• XML
• PHP
Drupal 8 uses YAML to define routes
foacie
o.rhv:
pt:'acie{ot}
ah /rhv/mnh'
dfut:
eals
_otn:
cnet
'DuaootolrFootolr:hwrhv'
rplfoCnrleoCnrle:soAcie
rqieet:
eurmns
mnh '09{}[-]2'
ot: [-]4-09{}
sboan 'w|'
udmi: wwm
hs:'sboan.xml.o'
ot {udmi}eapecm
Let’s start with a plain
“hello world”
using a /hello-world path
Defining the route in YAML
/modules/foo/foo.routing.yml
fohlowrd
o.el_ol:
pt:'hlowrd
ah /el-ol'
dfut:
eals
_otolr
cnrle:
'DuaootolrFootolr:elWrd
rplfoCnrleoCnrle:hlool'
rqieet:
eurmns
_ces 'RE
acs: TU'
Creating the controller
/modules/foo/lib/Controller/FooController.php
nmsaeDuaootolr
aepc rplfoCnrle;
ueSmoyCmoetHtFudtoepne
s yfnopnntponainRsos;
casFootolr{
ls oCnrle
pbi fnto hlool( {
ulc ucin elWrd)
$epne=nwRsos(HloWrd';
rsos
e epne'el ol!)
$epne>edr-st'otn-ye,'etpan)
rsos-haes>e(CnetTp' tx/li';
rtr $epne
eun rsos;
}
}
HloWrd
el ol!
Drupal 8 will use PSR-4 for module classes instead
of PSR-0
/modules/foo/lib/Controller/FooController.php
instead of
/modules/foo/lib/Drupal/foo/Controller/FooController.php
drupal.org issue: https://drupal.org/node/1971198
Returning a JSON response
nmsaeDuaootolr
aepc rplfoCnrle;
ueSmoyCmoetHtFudtosnepne
s yfnopnntponainJoRsos
casFootolr{
ls oCnrle
pbi fnto hlool( {
ulc ucin elWrd)
rtr nwJoRsos(
eun e snepne
ary'reig = 'el Wrd'
ra(getn' > Hlo ol!)
)
;
}
}
{getn""el Wrd"
"reig:Hlo ol!}
Returning "hello world" inside
Drupal content
using a /hello-world path
Defining the route in YAML
fohlowrd
o.el_ol:
pt:'hlowrd
ah /el-ol'
dfut:
eals
_otn:
cnet
'DuaootolrFootolr:elWrd
rplfoCnrleoCnrle:hlool'
_il:'reig
tte Getn'
rqieet:
eurmns
_emsin 'cescnet
priso: acs otn'
Returning a render array
nmsaeDuaootolr
aepc rplfoCnrle;
ueDuaoeCnrleotolrae
s rplCrotolrCnrleBs;
casFootolretnsCnrleBs {
ls oCnrle xed otolrae
pbi fnto hlool( {
ulc ucin elWrd)
$ul =ary)
bid
ra(;
$ul[#akp]=$hs>(HloWrd';
bid'mru'
ti-t'el ol!)
rtr $ul;
eun bid
}
}
Drupal 8 in action, the route to the method
What about dynamic page titles?
drupal_set_title() is being removed

Use _title_callback in the route defaults
dfut:
eals
_il_alak
tteclbc:
'DuaootolrFootolr:eTte
rplfoCnrleoCnrle:gtil'

Or return it as part of the main render array
$ul[#il' =..
bid'tte]
.
Returning a "hello world"
greeting configuration form
at /admin/config/people/greeting
Defining the route in YAML
foamngetn:
o.di_reig
pt:'amncni/epegetn'
ah /di/ofgpol/reig
dfut:
eals
_om 'DuaoomFoom
fr: rplfoFroFr'
rqieet:
eurmns
_emsin 'diitrgetn'
priso: amnse reig
ueDuaoeFrofgomae
s rplCromCniFrBs;
casFoometnsCniFrBs {
ls oFr xed ofgomae
pbi fnto gtomd){rtr 'o_om;}
ulc ucin eFrI(
eun fofr'
pbi fnto bidomary$om ary&fr_tt){
ulc ucin ulFr(ra fr, ra $omsae
$om'o_reig]=ary
fr[fogetn'
ra(
'tp'= 'etil'
#ye > txfed,
'tte = $hs>(Getn',
#il' > ti-t'reig)
'dfutvle = 'elwWrd'
#eal_au' > Hlo ol!,
)
;
rtr prn:bidom$om $omsae;
eun aet:ulFr(fr, fr_tt)
}
}
Drupal 8 in action, the route to the method
FormBase implements FormInterface
nmsaeDuaoeFr;
aepc rplCrom
itraeFrItrae{
nefc omnefc
pbi fnto gtomd)
ulc ucin eFrI(;
pbi fnto bidomary$om ary&fr_tt)
ulc ucin ulFr(ra fr, ra $omsae;
pbi fnto vldtFr(ra &fr,ary&fr_tt)
ulc ucin aiaeomary $om ra $omsae;
pbi fnto sbiFr(ra &fr,ary&fr_tt)
ulc ucin umtomary $om ra $omsae;
}
Advanced Routing
dfut:
eals
#Cnrltefl rsos aatfo Dua etacnet
oto h ul epne pr rm rpl xr otn
_otolr 'DuaokCnrleokotolr:okxot
cnrle: rplbootolrBoCnrle:boEpr'
#Ptcneti temi rgo adltDua d ters
u otn n h an ein n e rpl o h et
_otn:'DuaokCnrleokotolr:okedr
cnet rplbootolrBoCnrle:boRne'
#Gttebidommto o acasetnigaDua Fr
e h ulFr ehd f
ls xedn
rpl om
_om 'DuaokFroketnsom
fr: rplboomBoStigFr'
Entity defaults
dfut:
eals
#Cl bidomfrteato ett adoeainFr
al ulFr o h cin niy d prto om
_niyfr:'cinad
ett_om ato.d'
#Dslyals o txnm_oauayett ojcs
ipa
it f aooyvcblr niy bet
_niyls:'aooyvcblr'
ett_it txnm_oauay
#So tefl ve md o aue ett ojc
hw h ul iw oe f
sr niy bet
_niyve:'srfl'
ett_iw ue.ul
Passing parameters to the controller method
#Prmtrdfndi tept
aaee eie n h ah
pt:'cmet{omn}apoe
ah /omn/cmet/prv'
#Dfutprmtr
eal aaee
pt:'amnsrcuetps
ah /di/tutr/ye'
dfut:
eals
ett_ye 'oetp'
niytp: nd_ye
#Otoa (ohi tept adwt adfutvle
pinl bt n h ah n ih
eal au)
pt:'amncni/erhpt/ky}
ah /di/ofgsac/ah{es'
dfut:
eals
ky:NL
es UL
nd.vriwtps
oeoeve_ye:
pt:'amnsrcuetps
ah /di/tutr/ye'
dfut:
eals
_otn:
cnet
'DuaoeEttotolrEttLsCnrle:lsig
rplCrniyCnrleniyitotolr:itn'
ett_ye 'oetp'
niytp: nd_ye
_il:'otn tps
tte Cnet ye'
casEttLsCnrle etnsCnrleBs {
ls niyitotolr xed otolrae
pbi fnto lsig$niytp){
ulc ucin itn(ett_ye
rtr $hs>niyaae(
eun ti-ettMngr)
-gtitotolr$niytp)
>eLsCnrle(ett_ye
-rne(;
>edr)
}
}
Parameters are upcasted to entities by entity type id
cnatproa_ae
otc.esnlpg
pt:'ue/ue}cnat
ah /sr{sr/otc'
cnatst_aectgr:
otc.iepg_aeoy
pt:'cnat{otc_aeoy'
ah /otc/cnatctgr}
casCnatotolr{
ls otcCnrle
pbi fnto cnatesnlaeUeItrae$sr {.}
ulc ucin otcProaPg(srnefc ue) ..
pbi fnto cnatieae
ulc ucin otcStPg(
CtgrItrae$otc_aeoy=NL){.}
aeoynefc cnatctgr
UL ..
}
Explicitly converting parameters into entities
fohloue:
o.el_sr
pt:'{o_sr/el/ue}
ah /foue}hlo{sr'
#eg //el/
.. 1hlo2
dfut:
eals
_otn:'..Footolr:elUe'
cnet .oCnrle:hlosr
otos
pin:
prmtr:
aaees
foue:
o_sr
tp:'niyue'
ye ett:sr
#{o_sr wl as b pse a aue ett
foue} il lo e asd s
sr niy
Regular expressions requirements for parameters
#{p prmtrcnol b 'nbe o 'ial'
o} aaee a ny e eal' r dsbe
vesu.prto:
iw_ioeain
pt:'amnsrcuevesve/ve}{p'
ah /di/tutr/iw/iw{iw/o}
rqieet:
eurmns
o:'nbedsbe
p eal|ial'
#{sr prmtrcnol b anme
ue} aaee a ny e
ubr
ue.iw
srve:
pt:'ue/ue}
ah /sr{sr'
rqieet:
eurmns
ue:+
sr d
Access Check
_o_hl_o_as TU
yusalntps: RE
Drupal 8 doesn't implement Symfony2 Security
component, and manages access from routing
Symfony uses a separate Security component for controlling route access
that is too complex to integrate in Drupal 8.
Drupal 8 implements access checkers services, which will ignore, allow or
deny the access based on a requirement on the route.
Checking Permissions
nd.vriwtps
oeoeve_ye:
pt:'amnsrcuetps
ah /di/tutr/ye'
dfut:
eals
_otn:
cnet
'DuaoeEttotolrEttLsCnrle:lsig
rplCrniyCnrleniyitotolr:itn'
ett_ye 'oetp'
niytp: nd_ye
_il:'otn tps
tte Cnet ye'
rqieet:
eurmns
_emsin 'diitrcnettps
priso: amnse otn ye'
Still setting permissions in hook_permission()
fnto nd_emsin){
ucin oepriso(
rtr ary
eun ra(
'diitrcnettps = ary
amnse otn ye' > ra(
'il'= t'diitrcnettps)
tte > (Amnse otn ye',
'etitacs'= TU,
rsrc ces > RE
)
,
)
;
}

I asked for hook_permission() in IRC #drupal-contribute
<timplunkett> juanolalla: no plans to replace that AFAIK
Common access checkers provided by Drupal core
#Awy ps,o 'AS't awy fi adbokacs
las as r FLE o las al n lc ces
rqieet:
eurmns
_ces 'RE
acs: TU'
#Rl Issprtdb ""(n rl)o ""(l rls
oe D eaae y , ay oe r + al oe)
rqieet:
eurmns
_oe 'uhniae,di'
rl: atetctdamn
#Pse i teue i lge i
ass f h sr s ogd n
rqieet:
eurmns
_sri_ogdi:'RE
ue_slge_n TU'
Other useful access checkers provided
#Cek i ayal(/)teseiidmdlsaeeald
hcs f n/l ,+ h pcfe oue r nbe
rqieet:
eurmns
_ouedpnece:'oe+sac'
mdl_eednis nd
erh
#Cek acs t teseiidett_yeoeain
hcs ces o h pcfe niytp.prto
rqieet:
eurmns
_niyacs:'oeei'
ett_ces nd.dt
#Cek acs t teseiidett_yeett_ude
hcs ces o h pcfe niytp:niybnl
rqieet:
eurmns
_niycet_ces 'aooytr:txnm_oauay'
ett_raeacs: txnm_em{aooyvcblr}
Declaring your own custom access checker
Declare your requirement checker in .routing.yml
rqieet:
eurmns
_o_hl_o_as 'RE
yusalntps: TU'

Register an access checker class as a service (in .services.yml)
srie:
evcs
acs_hc.o.adl:
cescekfognaf
cas DuaocesGnafceshc
ls: rplfoAcsadlAcsCek
tg:
as
-{nm:acs_hc }
ae cescek
Writting your own custom access checker class
casGnafceshc ipeet SaiAcsCeknefc {
ls adlAcsCek mlmns ttcceshcItrae
pbi fnto apiso){
ulc ucin pleT(
rtr ary'yusalntps';
eun ra(_o_hl_o_as)
}
pbi fnto acs(ot $ot,Rqet$eus){
ulc ucin cesRue rue eus rqet
$eurmn =$ot-gteurmn(_o_hl_o_as)
rqieet
rue>eRqieet'yusalntps';
i (i_ra(hts,$ot-gtcee()
f !nary'tp' rue>eShms)
& $eurmn = 'RE){
& rqieet = TU'
rtr sai:DN;/ o rtr sai:ALW
eun ttc:EY / r eun ttc:LO
}/ N rtr masohrcekr wl dcd
/ o eun en te hces il eie
}
}
Access mode options, checking any or all requirements
nd.d_ae
oeadpg:
pt:'nd/d'
ah /oead
dfut:
eals
_il:'d pg'
tte Ad ae
_otn:'DuaoeCnrleoeotolr:dPg'
cnet rplndotolrNdCnrle:adae
otos
pin:
_cesmd:'N'
acs_oe AY
rqieet:
eurmns
_emsin 'diitrcnettps
priso: amnse otn ye'
_oeadacs:'oe
nd_d_ces nd'
Building Dynamic Routes
Implement a route subscriber class
/core/modules/system/Routing/RouteSubscriber.php
nmsaeDuaytmRuig
aepc rplsseotn;
ueDuaoeRuigRueusrbrae
s rplCrotnotSbcieBs;
ueSmoyCmoetRuigRue
s yfnopnnotnot;
ueSmoyCmoetRuigRueolcin
s yfnopnnotnotCleto;
/*
*
*Poie dnmcrue frteeamnsrto.
rvds yai ots o hm diitain
*
/
casRueusrbretnsRueusrbrae{
ls otSbcie xed otSbcieBs
poetdfnto rue(otCleto $olcin {.}
rtce ucin otsRueolcin cleto) ..
}
poetdfnto rue(otCleto $olcin {
rtce ucin otsRueolcin cleto)
frah(ittee( a $hm){
oec ls_hms) s tee
$ot =nwRue
rue
e ot(
'di/pernestig/ .$hm-nm,
amnapaac/etns'
tee>ae
ary
ra(
'fr'= 'DuaytmFrhmStigFr'
_om > rplsseomTeeetnsom,
'hm_ae = $hm-nm
teenm' > tee>ae
)
,
ary'priso'= 'diitrtee',
ra(_emsin > amnse hms)
)
;
$olcin>d(
cleto-ad
'ytmteestig_ .$hm-nm,$ot)
sse.hm_etns'
tee>ae rue;
}
}
Dependency injection
Keep your controllers clean and thin
Our classes shouldn't have hard-coded dependencies
casSnCnrle {
ls ogotolr
pbi fnto gtadmog){
ulc ucin eRnoSn(
/ d_ur( i ahr-oe dpnec
/ bqey) s
adcdd eedny
$og =d_ur(SLC nm FO {og})>ecCl)
sns
bqey'EET ae RM sns'-ftho(;
$og=$og[ad0 cut$og)-1]
sn
snsrn(, on(sns
);
rtr nwJoRsos(
eun e snepne
ary'og = $og
ra(sn' > sn)
)
;
}
}
Decoupling the dependency
poetd$aaae / DuaoeDtbsoncin
rtce dtbs; / rplCraaaeCneto;
pbi fnto gtadmog){
ulc ucin eRnoSn(
$og =$hs>aaae
sns
ti-dtbs
-qey'EETnm FO {og})>ecCl)
>ur(SLC ae RM sns'-ftho(;
rtr $og[ad0 cut$og)-1]
eun snsrn(, on(sns
);
}
Getting the dependency injected
ueDuaoeDtbsoncin
s rplCraaaeCneto;
ueDuaoeDpnecIjcinCnanrnetoItrae
s rplCreednynetootieIjcinnefc;
ueSmoyCmoetDpnecIjcinCnanrnefc;
s yfnopnneednynetootieItrae
casSnCnrle ipeet CnanrnetoItrae{
ls ogotolr mlmns otieIjcinnefc
poetd$aaae
rtce dtbs;
pbi fnto _cntutCneto $aaae {
ulc ucin _osrc(oncin dtbs)
$hs>aaae=$aaae
ti-dtbs
dtbs;
}
pbi sai fnto cet(otieItrae$otie){
ulc ttc ucin raeCnanrnefc cnanr
/ Isataetecnrle wt adtbs ojc
/ ntnit h otolr ih
aaae bet
rtr nwsai(cnanr>e(dtbs')
eun e ttc$otie-gt'aaae);
}
Want to see more coming?
/on#rplcnrbt
ji dua-otiue
Thank you!

More Related Content

PDF
RabbitMQ
PDF
Theme Development and Customization
PDF
穏やかにファイルを削除する
PPTX
Build a compiler in 2hrs - NCrafts Paris 2015
PDF
Refactoring to symfony components
PDF
The most exciting features of PHP 7.1
PDF
mapserver_install_linux
PDF
Augeas
RabbitMQ
Theme Development and Customization
穏やかにファイルを削除する
Build a compiler in 2hrs - NCrafts Paris 2015
Refactoring to symfony components
The most exciting features of PHP 7.1
mapserver_install_linux
Augeas

What's hot (20)

PDF
Frege is a Haskell for the JVM
PDF
Perl 6 by example
PDF
Symfony2 - WebExpo 2010
PDF
PhpBB meets Symfony2
PDF
Flow of events during Media Player creation in Android
TXT
Yy
TXT
Nouveau document texte
PDF
Introduction to JavaFX 2
PDF
Descobrindo a linguagem Perl
PDF
Puppet modules for Fun and Profit
PDF
JavaFX, because you're worth it
PDF
Create Custom Post Type Plugin
TXT
C99.php
PDF
Introdução ao Perl 6
PDF
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
PDF
Perl6 in-production
PDF
Build a custom (micro)framework with ZF2 Components (as building blocks)
PDF
I, For One, Welcome Our New Perl6 Overlords
KEY
DPC 2012 : PHP in the Dark Workshop
PDF
News of the Symfony2 World
Frege is a Haskell for the JVM
Perl 6 by example
Symfony2 - WebExpo 2010
PhpBB meets Symfony2
Flow of events during Media Player creation in Android
Yy
Nouveau document texte
Introduction to JavaFX 2
Descobrindo a linguagem Perl
Puppet modules for Fun and Profit
JavaFX, because you're worth it
Create Custom Post Type Plugin
C99.php
Introdução ao Perl 6
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
Perl6 in-production
Build a custom (micro)framework with ZF2 Components (as building blocks)
I, For One, Welcome Our New Perl6 Overlords
DPC 2012 : PHP in the Dark Workshop
News of the Symfony2 World
Ad

Similar to Drupal 8 in action, the route to the method (20)

PDF
Beginner workshop to angularjs presentation at Google
PDF
One page app with AngularJS
PDF
SecureSocial - Authentication for Play Framework
PDF
JavaScript Design Patterns
PDF
Javascript fundamentals for php developers
PDF
Nginx Scripting - Extending Nginx Functionalities with Lua
PDF
Devinsampa nginx-scripting
PDF
Auto-loading of Drupal CCK Nodes
PDF
Creating windows store java script apps
PDF
Automated tests - facts and myths
PDF
Clojurescript up and running
PDF
Hubot: a look inside our robot friend
PPT
GeeCON 2013 - EJB application guided by tests
PDF
Javascript: The Important Bits
PDF
Angular.js + Rails at WeWork or: The Accidental Feature
PDF
Drush - use full power - DrupalCamp Donetsk 2014
PDF
Drush - use full power - Alexander Schedrov
PDF
Noah Zoschke at Waza 2013: Heroku Secrets
PDF
Puppet Modules for Fun and Profit
PDF
Starting out with Ember.js
Beginner workshop to angularjs presentation at Google
One page app with AngularJS
SecureSocial - Authentication for Play Framework
JavaScript Design Patterns
Javascript fundamentals for php developers
Nginx Scripting - Extending Nginx Functionalities with Lua
Devinsampa nginx-scripting
Auto-loading of Drupal CCK Nodes
Creating windows store java script apps
Automated tests - facts and myths
Clojurescript up and running
Hubot: a look inside our robot friend
GeeCON 2013 - EJB application guided by tests
Javascript: The Important Bits
Angular.js + Rails at WeWork or: The Accidental Feature
Drush - use full power - DrupalCamp Donetsk 2014
Drush - use full power - Alexander Schedrov
Noah Zoschke at Waza 2013: Heroku Secrets
Puppet Modules for Fun and Profit
Starting out with Ember.js
Ad

Recently uploaded (20)

PPTX
Machine Learning_overview_presentation.pptx
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
Big Data Technologies - Introduction.pptx
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Machine learning based COVID-19 study performance prediction
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
Cloud computing and distributed systems.
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
Machine Learning_overview_presentation.pptx
NewMind AI Weekly Chronicles - August'25-Week II
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
Chapter 3 Spatial Domain Image Processing.pdf
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Per capita expenditure prediction using model stacking based on satellite ima...
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Big Data Technologies - Introduction.pptx
Unlocking AI with Model Context Protocol (MCP)
Machine learning based COVID-19 study performance prediction
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
MIND Revenue Release Quarter 2 2025 Press Release
Cloud computing and distributed systems.
Digital-Transformation-Roadmap-for-Companies.pptx
20250228 LYD VKU AI Blended-Learning.pptx

Drupal 8 in action, the route to the method

  • 1. Drupal 8 in action, the route to the method @juanolalla #DrupalCampEs
  • 2. about.me/juanolalla Juan Olalla web developer focused on drupal at @ideup (@gowex) Motivation I’ve recently been contributing to Drupal 8 core and I want to share with you what I've learned
  • 5. Goodbye to hook_menu() for routing and for everything else... Routing Routes defined in routing.yml and controllers Menu links Defined in hook_default_menu_links() Local actions Plugins defined in local_actions.yml Local tasks Plugins defined in local_tasks.yml Contextual links Plugins defined in contextual_links.yml Breadcrumbs Implementing BreadcrumbBuilder plugins Links can be related regardless of the path, managed by machine names.
  • 6. Drupal 8 uses Symfony2 Routing component And also uses Symfony CMF RoutingBundle for dynamic routing
  • 7. What is a route?
  • 8. A route is an object defined by 1. Path 2. Default values 3. Requirements 4. Options 5. Host 6. Schemes 7. Methods
  • 9. ueSmoyCmoetRuigRue s yfnopnnotnot; $ot =nwRue rue e ot( 'acie{ot},/ pt /rhv/mnh' / ah ary'otolr = 'hwrhv',/ dfutvle ra(cnrle' > soAcie) / eal aus ary ra( 'ot'= '09{}[-]2' mnh > [-]4-09{}, 'udmi'= 'w|' sboan > wwm, ) / rqieet , / eurmns ary) / otos ra(, / pin 'sboan.xml.o' / hs {udmi}eapecm, / ot ary) / shms ra(, / cee ary)/ mtos ra( / ehd ) ;
  • 10. The Routing component gets routes from • PHP code: • a RouteCollection object • closures • class annotations • External files: • YAML • XML • PHP
  • 11. Drupal 8 uses YAML to define routes foacie o.rhv: pt:'acie{ot} ah /rhv/mnh' dfut: eals _otn: cnet 'DuaootolrFootolr:hwrhv' rplfoCnrleoCnrle:soAcie rqieet: eurmns mnh '09{}[-]2' ot: [-]4-09{} sboan 'w|' udmi: wwm hs:'sboan.xml.o' ot {udmi}eapecm
  • 12. Let’s start with a plain “hello world” using a /hello-world path
  • 13. Defining the route in YAML /modules/foo/foo.routing.yml fohlowrd o.el_ol: pt:'hlowrd ah /el-ol' dfut: eals _otolr cnrle: 'DuaootolrFootolr:elWrd rplfoCnrleoCnrle:hlool' rqieet: eurmns _ces 'RE acs: TU'
  • 14. Creating the controller /modules/foo/lib/Controller/FooController.php nmsaeDuaootolr aepc rplfoCnrle; ueSmoyCmoetHtFudtoepne s yfnopnntponainRsos; casFootolr{ ls oCnrle pbi fnto hlool( { ulc ucin elWrd) $epne=nwRsos(HloWrd'; rsos e epne'el ol!) $epne>edr-st'otn-ye,'etpan) rsos-haes>e(CnetTp' tx/li'; rtr $epne eun rsos; } }
  • 16. Drupal 8 will use PSR-4 for module classes instead of PSR-0 /modules/foo/lib/Controller/FooController.php instead of /modules/foo/lib/Drupal/foo/Controller/FooController.php drupal.org issue: https://drupal.org/node/1971198
  • 17. Returning a JSON response nmsaeDuaootolr aepc rplfoCnrle; ueSmoyCmoetHtFudtosnepne s yfnopnntponainJoRsos casFootolr{ ls oCnrle pbi fnto hlool( { ulc ucin elWrd) rtr nwJoRsos( eun e snepne ary'reig = 'el Wrd' ra(getn' > Hlo ol!) ) ; } }
  • 19. Returning "hello world" inside Drupal content using a /hello-world path
  • 20. Defining the route in YAML fohlowrd o.el_ol: pt:'hlowrd ah /el-ol' dfut: eals _otn: cnet 'DuaootolrFootolr:elWrd rplfoCnrleoCnrle:hlool' _il:'reig tte Getn' rqieet: eurmns _emsin 'cescnet priso: acs otn'
  • 21. Returning a render array nmsaeDuaootolr aepc rplfoCnrle; ueDuaoeCnrleotolrae s rplCrotolrCnrleBs; casFootolretnsCnrleBs { ls oCnrle xed otolrae pbi fnto hlool( { ulc ucin elWrd) $ul =ary) bid ra(; $ul[#akp]=$hs>(HloWrd'; bid'mru' ti-t'el ol!) rtr $ul; eun bid } }
  • 23. What about dynamic page titles? drupal_set_title() is being removed Use _title_callback in the route defaults dfut: eals _il_alak tteclbc: 'DuaootolrFootolr:eTte rplfoCnrleoCnrle:gtil' Or return it as part of the main render array $ul[#il' =.. bid'tte] .
  • 24. Returning a "hello world" greeting configuration form at /admin/config/people/greeting
  • 25. Defining the route in YAML foamngetn: o.di_reig pt:'amncni/epegetn' ah /di/ofgpol/reig dfut: eals _om 'DuaoomFoom fr: rplfoFroFr' rqieet: eurmns _emsin 'diitrgetn' priso: amnse reig
  • 26. ueDuaoeFrofgomae s rplCromCniFrBs; casFoometnsCniFrBs { ls oFr xed ofgomae pbi fnto gtomd){rtr 'o_om;} ulc ucin eFrI( eun fofr' pbi fnto bidomary$om ary&fr_tt){ ulc ucin ulFr(ra fr, ra $omsae $om'o_reig]=ary fr[fogetn' ra( 'tp'= 'etil' #ye > txfed, 'tte = $hs>(Getn', #il' > ti-t'reig) 'dfutvle = 'elwWrd' #eal_au' > Hlo ol!, ) ; rtr prn:bidom$om $omsae; eun aet:ulFr(fr, fr_tt) } }
  • 28. FormBase implements FormInterface nmsaeDuaoeFr; aepc rplCrom itraeFrItrae{ nefc omnefc pbi fnto gtomd) ulc ucin eFrI(; pbi fnto bidomary$om ary&fr_tt) ulc ucin ulFr(ra fr, ra $omsae; pbi fnto vldtFr(ra &fr,ary&fr_tt) ulc ucin aiaeomary $om ra $omsae; pbi fnto sbiFr(ra &fr,ary&fr_tt) ulc ucin umtomary $om ra $omsae; }
  • 30. dfut: eals #Cnrltefl rsos aatfo Dua etacnet oto h ul epne pr rm rpl xr otn _otolr 'DuaokCnrleokotolr:okxot cnrle: rplbootolrBoCnrle:boEpr' #Ptcneti temi rgo adltDua d ters u otn n h an ein n e rpl o h et _otn:'DuaokCnrleokotolr:okedr cnet rplbootolrBoCnrle:boRne' #Gttebidommto o acasetnigaDua Fr e h ulFr ehd f ls xedn rpl om _om 'DuaokFroketnsom fr: rplboomBoStigFr'
  • 31. Entity defaults dfut: eals #Cl bidomfrteato ett adoeainFr al ulFr o h cin niy d prto om _niyfr:'cinad ett_om ato.d' #Dslyals o txnm_oauayett ojcs ipa it f aooyvcblr niy bet _niyls:'aooyvcblr' ett_it txnm_oauay #So tefl ve md o aue ett ojc hw h ul iw oe f sr niy bet _niyve:'srfl' ett_iw ue.ul
  • 32. Passing parameters to the controller method #Prmtrdfndi tept aaee eie n h ah pt:'cmet{omn}apoe ah /omn/cmet/prv' #Dfutprmtr eal aaee pt:'amnsrcuetps ah /di/tutr/ye' dfut: eals ett_ye 'oetp' niytp: nd_ye #Otoa (ohi tept adwt adfutvle pinl bt n h ah n ih eal au) pt:'amncni/erhpt/ky} ah /di/ofgsac/ah{es' dfut: eals ky:NL es UL
  • 33. nd.vriwtps oeoeve_ye: pt:'amnsrcuetps ah /di/tutr/ye' dfut: eals _otn: cnet 'DuaoeEttotolrEttLsCnrle:lsig rplCrniyCnrleniyitotolr:itn' ett_ye 'oetp' niytp: nd_ye _il:'otn tps tte Cnet ye' casEttLsCnrle etnsCnrleBs { ls niyitotolr xed otolrae pbi fnto lsig$niytp){ ulc ucin itn(ett_ye rtr $hs>niyaae( eun ti-ettMngr) -gtitotolr$niytp) >eLsCnrle(ett_ye -rne(; >edr) } }
  • 34. Parameters are upcasted to entities by entity type id cnatproa_ae otc.esnlpg pt:'ue/ue}cnat ah /sr{sr/otc' cnatst_aectgr: otc.iepg_aeoy pt:'cnat{otc_aeoy' ah /otc/cnatctgr} casCnatotolr{ ls otcCnrle pbi fnto cnatesnlaeUeItrae$sr {.} ulc ucin otcProaPg(srnefc ue) .. pbi fnto cnatieae ulc ucin otcStPg( CtgrItrae$otc_aeoy=NL){.} aeoynefc cnatctgr UL .. }
  • 35. Explicitly converting parameters into entities fohloue: o.el_sr pt:'{o_sr/el/ue} ah /foue}hlo{sr' #eg //el/ .. 1hlo2 dfut: eals _otn:'..Footolr:elUe' cnet .oCnrle:hlosr otos pin: prmtr: aaees foue: o_sr tp:'niyue' ye ett:sr #{o_sr wl as b pse a aue ett foue} il lo e asd s sr niy
  • 36. Regular expressions requirements for parameters #{p prmtrcnol b 'nbe o 'ial' o} aaee a ny e eal' r dsbe vesu.prto: iw_ioeain pt:'amnsrcuevesve/ve}{p' ah /di/tutr/iw/iw{iw/o} rqieet: eurmns o:'nbedsbe p eal|ial' #{sr prmtrcnol b anme ue} aaee a ny e ubr ue.iw srve: pt:'ue/ue} ah /sr{sr' rqieet: eurmns ue:+ sr d
  • 38. Drupal 8 doesn't implement Symfony2 Security component, and manages access from routing Symfony uses a separate Security component for controlling route access that is too complex to integrate in Drupal 8. Drupal 8 implements access checkers services, which will ignore, allow or deny the access based on a requirement on the route.
  • 40. Still setting permissions in hook_permission() fnto nd_emsin){ ucin oepriso( rtr ary eun ra( 'diitrcnettps = ary amnse otn ye' > ra( 'il'= t'diitrcnettps) tte > (Amnse otn ye', 'etitacs'= TU, rsrc ces > RE ) , ) ; } I asked for hook_permission() in IRC #drupal-contribute <timplunkett> juanolalla: no plans to replace that AFAIK
  • 41. Common access checkers provided by Drupal core #Awy ps,o 'AS't awy fi adbokacs las as r FLE o las al n lc ces rqieet: eurmns _ces 'RE acs: TU' #Rl Issprtdb ""(n rl)o ""(l rls oe D eaae y , ay oe r + al oe) rqieet: eurmns _oe 'uhniae,di' rl: atetctdamn #Pse i teue i lge i ass f h sr s ogd n rqieet: eurmns _sri_ogdi:'RE ue_slge_n TU'
  • 42. Other useful access checkers provided #Cek i ayal(/)teseiidmdlsaeeald hcs f n/l ,+ h pcfe oue r nbe rqieet: eurmns _ouedpnece:'oe+sac' mdl_eednis nd erh #Cek acs t teseiidett_yeoeain hcs ces o h pcfe niytp.prto rqieet: eurmns _niyacs:'oeei' ett_ces nd.dt #Cek acs t teseiidett_yeett_ude hcs ces o h pcfe niytp:niybnl rqieet: eurmns _niycet_ces 'aooytr:txnm_oauay' ett_raeacs: txnm_em{aooyvcblr}
  • 43. Declaring your own custom access checker Declare your requirement checker in .routing.yml rqieet: eurmns _o_hl_o_as 'RE yusalntps: TU' Register an access checker class as a service (in .services.yml) srie: evcs acs_hc.o.adl: cescekfognaf cas DuaocesGnafceshc ls: rplfoAcsadlAcsCek tg: as -{nm:acs_hc } ae cescek
  • 44. Writting your own custom access checker class casGnafceshc ipeet SaiAcsCeknefc { ls adlAcsCek mlmns ttcceshcItrae pbi fnto apiso){ ulc ucin pleT( rtr ary'yusalntps'; eun ra(_o_hl_o_as) } pbi fnto acs(ot $ot,Rqet$eus){ ulc ucin cesRue rue eus rqet $eurmn =$ot-gteurmn(_o_hl_o_as) rqieet rue>eRqieet'yusalntps'; i (i_ra(hts,$ot-gtcee() f !nary'tp' rue>eShms) & $eurmn = 'RE){ & rqieet = TU' rtr sai:DN;/ o rtr sai:ALW eun ttc:EY / r eun ttc:LO }/ N rtr masohrcekr wl dcd / o eun en te hces il eie } }
  • 45. Access mode options, checking any or all requirements nd.d_ae oeadpg: pt:'nd/d' ah /oead dfut: eals _il:'d pg' tte Ad ae _otn:'DuaoeCnrleoeotolr:dPg' cnet rplndotolrNdCnrle:adae otos pin: _cesmd:'N' acs_oe AY rqieet: eurmns _emsin 'diitrcnettps priso: amnse otn ye' _oeadacs:'oe nd_d_ces nd'
  • 46. Building Dynamic Routes Implement a route subscriber class
  • 47. /core/modules/system/Routing/RouteSubscriber.php nmsaeDuaytmRuig aepc rplsseotn; ueDuaoeRuigRueusrbrae s rplCrotnotSbcieBs; ueSmoyCmoetRuigRue s yfnopnnotnot; ueSmoyCmoetRuigRueolcin s yfnopnnotnotCleto; /* * *Poie dnmcrue frteeamnsrto. rvds yai ots o hm diitain * / casRueusrbretnsRueusrbrae{ ls otSbcie xed otSbcieBs poetdfnto rue(otCleto $olcin {.} rtce ucin otsRueolcin cleto) .. }
  • 48. poetdfnto rue(otCleto $olcin { rtce ucin otsRueolcin cleto) frah(ittee( a $hm){ oec ls_hms) s tee $ot =nwRue rue e ot( 'di/pernestig/ .$hm-nm, amnapaac/etns' tee>ae ary ra( 'fr'= 'DuaytmFrhmStigFr' _om > rplsseomTeeetnsom, 'hm_ae = $hm-nm teenm' > tee>ae ) , ary'priso'= 'diitrtee', ra(_emsin > amnse hms) ) ; $olcin>d( cleto-ad 'ytmteestig_ .$hm-nm,$ot) sse.hm_etns' tee>ae rue; } }
  • 49. Dependency injection Keep your controllers clean and thin
  • 50. Our classes shouldn't have hard-coded dependencies casSnCnrle { ls ogotolr pbi fnto gtadmog){ ulc ucin eRnoSn( / d_ur( i ahr-oe dpnec / bqey) s adcdd eedny $og =d_ur(SLC nm FO {og})>ecCl) sns bqey'EET ae RM sns'-ftho(; $og=$og[ad0 cut$og)-1] sn snsrn(, on(sns ); rtr nwJoRsos( eun e snepne ary'og = $og ra(sn' > sn) ) ; } }
  • 51. Decoupling the dependency poetd$aaae / DuaoeDtbsoncin rtce dtbs; / rplCraaaeCneto; pbi fnto gtadmog){ ulc ucin eRnoSn( $og =$hs>aaae sns ti-dtbs -qey'EETnm FO {og})>ecCl) >ur(SLC ae RM sns'-ftho(; rtr $og[ad0 cut$og)-1] eun snsrn(, on(sns ); }
  • 52. Getting the dependency injected ueDuaoeDtbsoncin s rplCraaaeCneto; ueDuaoeDpnecIjcinCnanrnetoItrae s rplCreednynetootieIjcinnefc; ueSmoyCmoetDpnecIjcinCnanrnefc; s yfnopnneednynetootieItrae casSnCnrle ipeet CnanrnetoItrae{ ls ogotolr mlmns otieIjcinnefc poetd$aaae rtce dtbs; pbi fnto _cntutCneto $aaae { ulc ucin _osrc(oncin dtbs) $hs>aaae=$aaae ti-dtbs dtbs; } pbi sai fnto cet(otieItrae$otie){ ulc ttc ucin raeCnanrnefc cnanr / Isataetecnrle wt adtbs ojc / ntnit h otolr ih aaae bet rtr nwsai(cnanr>e(dtbs') eun e ttc$otie-gt'aaae); }
  • 53. Want to see more coming? /on#rplcnrbt ji dua-otiue