2.2.1: Routes and Layout Handles
2.2: Front-end Basics
In this section, we'll begin building out the real content of our Product Questions feature on the product detail page.
Routes and Layout Handles
Within our module, the file view/frontend/layout/catalog_product_view.xml
controls the content we are injecting into the
product detail page. We've more or less glossed over the mechanics of this file until now. It's time to get acquainted with it!
Before examining the contents of a layout XML file, however, the first question we ought to ask is why a file of this particular name affects this particular page. How do we know what filename to create when we want to update layout in a particular area?
To discover this, let's use an example a little more straightforward than the product detail page. On your storefront, if you haven't yet registered a customer account, do so now and log in. Visit My Account from the site's top navigation, then "My Orders" in the left navigation menu within your account. Once you've arrived here, you should be able to observe that the URL path for this particular page is:
/sales/order/history
Basically all destinations on your storefront have just such a three-segment URL path. (Even when a URL path contains only
two segments - as you'll observe with /checkout/cart
, there is an "implied" third segment: index
. And the "implied"
segments of the simple URL path /checkout
expand out to /checkout/index/index
.)
Core Concept
You may notice that some URLs on the storefront include more than three segments, such as the URL for viewing a specific order:
/sales/order/view/order_id/{id}
. Typically, all segments after the first three comprise key/value pairs that get passed in as if they were querystring parameters. So by the time the aforementioned URL path results in the/sales/order/view
controller being executed, available request parameters includeorder_id
with a value corresponding with the 5th URL segment.
Three significant URL segments ... that looks an awful lot like the pattern we see in our existing layout file. You might
guess, then, that the proper layout filename for updating content on the My Account order view page is sales_order_history.xml
.
And you'd be right! Except ... there's a potential wrinkle. To understand it, let's go to the source of truth for how URLs
are directed to the right application logic: routes.
The module config file routes.xml
defines routes, which are responsible for matching a URL pattern (typically the first URL
segment) to a module where controller classes will be located. This is another config file that is always applicable to one
area of the site or other, and so the relevant route for /sales/order/history
is located in
vendor/magento/module-sales/etc/frontend/routes.xml
. Let's take a peek at the contents:
<router id="standard">
<route id="sales" frontName="sales">
<module name="Magento_Sales" />
</route>
</router>
Different "router" classes in Magento provide different logic, and we can see here that the routes being defined are within
the scope of the "standard" router, which is the one virtually all of your front-end routes will use as well. A <route>
is defined with a particular frontName
, used to match the first segment of the URL, and with a <module>
node instructing
Magento where to look for controller classes. This route essentially says "when a URL begins with /sales
, look for matching
controller files in the Magento_Sales
module." We'll look more closely at how the remaining URL segments are matched to
a controller in a later lesson.
The key aspect of this route configuration to note here is the inclusion of both a frontName
attribute and an id
attribute.
As mentioned, it is the frontName
that is used to match the actual URL path of an actual request. The id
attribute,
on the other hand, is used to form the final name of the layout files matching a particular destination. If this same route
file contained, say, this config:
<router id="standard">
<route id="salesroutes" frontName="sales">
<module name="Magento_Sales" />
</route>
</router>
... then we would expect to find layout files named salesroutes_order_history.xml
containing the layout affecting the
/sales/order/history
page. Fortunately, the id
and frontName
of virtually all routes in Magento are identical, so
the URL segments themselves are more or less predictive of the relevant layout filenames.
Layout Update Handles
The string formed by a route ID and significant URL segments, such as sales_order_history
, is what is called a layout
update "handle." This type of handle - the one uniquely corresponding to a page - is the most common type of handle, but
there are others.
The default
handle is one that's applied to all pages. You can find default.xml
files in the view/*/layout
directory
of many modules, and your own modules can include it when you want to inject layout instructions that are relevant to all pages.
The version in the Magento_Theme
module (vendor/magento/module-theme/view/frontend/layout/default.xml
) contains the
foundational layout components upon which all other layout is built.
When a controller renders a page, the layout system uses the default
handle and the page-specific handle (like sales_order_history
),
then loads and merges all layout files with either of those filenames to form the final page layout structure.
Other layout handles can be applied as well, by controllers or by other layout files, to facilitate applying common layout
elements to similar pages. Take, for example, the handle customer_account
. The Magento_Customer
module contains a file
matching this handle (customer_account.xml
), but the handle itself doesn't correspond with a particular URL.
(customer_account_index
does.) But if we look at some of the other layout files in the same module, we'll see this:
<update handle="customer_account"/>
This instructs the layout system to add the customer_account
layout update handle to the list that is applied and loaded
for the page. customer_account.xml
contains layout instructions common to all "My Account" pages and avoids the need
for repeating them in each unique layout file.
Finding the Product Page Handle
There's a reason we didn't start with the page our custom feature is actually concerned with - the product detail page -
in our discussion of matching layout update handles to URL paths. Visit a product page on your site, and you'll notice
the URL is something like /montana-wind-jacket.html
or /zing-jump-rope.html
. (At least, unless your store's configuration
or the state of its data differs from ours.) Depending on your Store Config, the categories you used to navigate to the product
might also be represented as URL segments, but nothing resembling a common "product detail page" URL path that we could
have translated into a layout update handle.
To facilitate SEO-friendly URLs, Magento rewrites content-rich URL paths like the above to the "real" underlying paths
that follow the usual frontname/segments pattern. You can crack open and examine the database table url_rewrite
if you
want to see this in action. When a product detail page is loaded, by the time Magento is resolving the route, the URL
path being examined is /catalog/product/view
.
Similar rewrite patterns are used to direct category pages to the path /catalog/category/view
and CMS pages to the path
/cms/page/view
.
It's a perhaps frustrating amount of detective work to discover our ultimate goal - catalog_product_view.xml
as the layout
filename that affects the product detail page. But you'll deal with these layout update handles enough that you're unlikely
to forget them!