{"result":{"depiction_url":null,"edges":{"references":{"objects":[{"created":"2020-05-30T05:47:51Z","object_id":{"id":1279,"is_a":["text","documentation"],"name":"doc_glossary","title":"Glossary","uri":"https:\/\/zotonic.com\/id\/1279"},"seq":1000000},{"created":"2020-05-30T05:47:51Z","object_id":{"id":1296,"is_a":["text","documentation","reference","module"],"name":"doc_module_mod_base","title":"mod_base","uri":"https:\/\/zotonic.com\/id\/1296"},"seq":1000000},{"created":"2020-05-30T05:47:51Z","object_id":{"id":321,"is_a":["meta","category"],"name":"controller","title":"Controllers","uri":"https:\/\/test.zotonic.com\/id\/321"},"seq":1000000}],"predicate":{"id":332,"is_a":["meta","predicate"],"name":"references","title":{"_type":"trans","tr":{"en":"References"}},"uri":"https:\/\/zotonic.com\/id\/references"}}},"id":1540,"is_a":["text","documentation","developerguide"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1540"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_developerguide_controllers","page_url":{"en":"https:\/\/zotonic.com\/docs\/1540\/controllers","x-default":"https:\/\/zotonic.com\/docs\/1540\/controllers"},"preview_url":null,"resource":{"body":"<div>\n            \n  <div class=\"section\">\n\n<p><a class=\"reference internal\" href=\"\/id\/doc_glossary#term-controller\"><span class=\"xref std std-term\">Controllers<\/span><\/a> are the Erlang modules which decide\nwhat happens when a browser requests a page. Zotonic looks at the\n<a class=\"reference internal\" href=\"\/id\/doc_glossary#term-dispatch-rule\"><span class=\"xref std std-term\">dispatch rules<\/span><\/a> that match the requested URL,\nand if a dispatch rule matches, the controller that is named in the\ndispatch rule is used to handle the request.<\/p>\n<div class=\"section\">\n<h2>Anatomy of a controller<\/h2>\n<p>Say we have the following dispatch rule, handling <code class=\"docutils literal notranslate\"><span class=\"pre\">https:\/\/localhost\/example<\/span><\/code>:<\/p>\n<div class=\"highlight-erlang notranslate\"><div class=\"highlight\"><pre><span><\/span><span class=\"p\">{<\/span><span class=\"n\">example_url<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span> <span class=\"s\">&quot;example&quot;<\/span> <span class=\"p\">],<\/span> <span class=\"n\">controller_example<\/span><span class=\"p\">,<\/span> <span class=\"p\">[]},<\/span>\n<\/pre><\/div>\n<\/div>\n<p>When hitting <code class=\"docutils literal notranslate\"><span class=\"pre\">\/example<\/span><\/code>, the <code class=\"docutils literal notranslate\"><span class=\"pre\">controller_example<\/span><\/code> controller will be\ninitialized and callback functions on the controller will be\ncalled, according to the HTTP protocol flow.<\/p>\n<p>Controllers are pretty self-documenting, thanks to the names of the\ncowmachine callback functions. For instance, when you define a\nfunction <code class=\"docutils literal notranslate\"><span class=\"pre\">resource_exists\/1<\/span><\/code>, it will be called to decide if\nthe page should return a 404.<\/p>\n<p>The simplest controller to serve HTML:<\/p>\n<div class=\"highlight-erlang notranslate\"><div class=\"highlight\"><pre><span><\/span><span class=\"p\">-<\/span><span class=\"ni\">module<\/span><span class=\"p\">(<\/span><span class=\"n\">controller_example<\/span><span class=\"p\">).<\/span>\n\n<span class=\"p\">-<\/span><span class=\"ni\">export<\/span><span class=\"p\">([<\/span> <span class=\"n\">process<\/span><span class=\"o\">\/<\/span><span class=\"mi\">4<\/span> <span class=\"p\">]).<\/span>\n\n<span class=\"nf\">process<\/span><span class=\"p\">(_<\/span><span class=\"nv\">Method<\/span><span class=\"p\">,<\/span> <span class=\"p\">_<\/span><span class=\"nv\">AcceptedCT<\/span><span class=\"p\">,<\/span> <span class=\"p\">_<\/span><span class=\"nv\">ProvidedCT<\/span><span class=\"p\">,<\/span> <span class=\"nv\">Context<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span>\n    <span class=\"p\">{<\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"s\">&quot;&lt;h1&gt;Hello&lt;\/h1&gt;&quot;<\/span><span class=\"o\">&gt;&gt;<\/span><span class=\"p\">,<\/span> <span class=\"nv\">Context<\/span><span class=\"p\">}.<\/span>\n<\/pre><\/div>\n<\/div>\n<\/div>\n<div class=\"section\">\n<a name=\"guide-render\"><\/a><h2>Rendering templates<\/h2>\n<p>To return the rendered output of a template file in the module’s\n<code class=\"file docutils literal notranslate\"><span class=\"pre\">priv\/templates<\/span><\/code> directory, use <code class=\"docutils literal notranslate\"><span class=\"pre\">z_template:render_to_iolist\/3<\/span><\/code>:<\/p>\n<div class=\"highlight-erlang notranslate\"><div class=\"highlight\"><pre><span><\/span><span class=\"p\">-<\/span><span class=\"ni\">module<\/span><span class=\"p\">(<\/span><span class=\"n\">controller_example<\/span><span class=\"p\">).<\/span>\n\n<span class=\"p\">-<\/span><span class=\"ni\">export<\/span><span class=\"p\">([<\/span> <span class=\"n\">process<\/span><span class=\"o\">\/<\/span><span class=\"mi\">4<\/span> <span class=\"p\">])<\/span>\n\n<span class=\"nf\">process<\/span><span class=\"p\">(_<\/span><span class=\"nv\">Method<\/span><span class=\"p\">,<\/span> <span class=\"p\">_<\/span><span class=\"nv\">AcceptedCT<\/span><span class=\"p\">,<\/span> <span class=\"p\">_<\/span><span class=\"nv\">ProvidedCT<\/span><span class=\"p\">,<\/span> <span class=\"nv\">Context<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span>\n    <span class=\"c\">% foo and bam will be available as template variables in mytemplate.tpl.<\/span>\n    <span class=\"nv\">Vars<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n       <span class=\"p\">{<\/span><span class=\"n\">foo<\/span><span class=\"p\">,<\/span> <span class=\"o\">&lt;&lt;<\/span><span class=\"s\">&quot;bar&quot;<\/span><span class=\"o\">&gt;&gt;<\/span><span class=\"p\">},<\/span>\n       <span class=\"p\">{<\/span><span class=\"n\">bam<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1234<\/span><span class=\"p\">}<\/span>\n    <span class=\"p\">],<\/span>\n    <span class=\"nn\">z_template<\/span><span class=\"p\">:<\/span><span class=\"nf\">render_to_iolist<\/span><span class=\"p\">(<\/span><span class=\"s\">&quot;mytemplate.tpl&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nv\">Vars<\/span><span class=\"p\">,<\/span> <span class=\"nv\">Context<\/span><span class=\"p\">).<\/span>\n<\/pre><\/div>\n<\/div>\n<p>If you need more examples, <a class=\"reference internal\" href=\"\/id\/doc_module_mod_base\"><span class=\"std std-ref\">mod_base<\/span><\/a> contains many controllers,\nimplementing basic HTTP interaction but also redirects, websockets, et\ncetera. The <a class=\"reference internal\" href=\"\/id\/controller#controllers\"><span class=\"std std-ref\">Controllers<\/span><\/a> page lists all available controllers in\nthe Zotonic core.<\/p>\n<p>The <a class=\"reference external\" href=\"https:\/\/github.com\/zotonic\/cowmachine\/wiki\">Cowmachine documentation<\/a> is\nhelpful for understanding controllers.<\/p>\n<\/div>\n<div class=\"section\">\n<a name=\"guide-controllers-cowmachine\"><\/a><h2>Differences between Cowmachine and Basho’s Webmachine<\/h2>\n<p>Zotonic’s fork of Webmachine has been named <code class=\"docutils literal notranslate\"><span class=\"pre\">cowmachine<\/span><\/code> and lives in its\nseparate repository at <a class=\"reference external\" href=\"https:\/\/github.com\/zotonic\/cowmachine\">https:\/\/github.com\/zotonic\/cowmachine<\/a>).<\/p>\n<p>The main differences with Basho’s Webmachine are:<\/p>\n<ul class=\"simple\">\n<li>Uses Cowboy instead of MochiWeb<\/li>\n<li>All callbacks have a single handler<\/li>\n<li>Pluggable dispatch handler<\/li>\n<li>Support for the HTTP <code class=\"docutils literal notranslate\"><span class=\"pre\">Upgrade:<\/span><\/code> header<\/li>\n<li>Optional caching of controller callbacks results<\/li>\n<li>Dispatch handler can redirect requests<\/li>\n<li>Use of process dictionary has been removed<\/li>\n<li><code class=\"docutils literal notranslate\"><span class=\"pre\">webmachine_request<\/span><\/code> is now a normal (not parametrized) module<\/li>\n<li>Extra logging<\/li>\n<li>ping and init callbacks are removed<\/li>\n<\/ul>\n<p>Together, this is a significant simplification and speed boost.<\/p>\n<\/div>\n<\/div>\n\n\n           <\/div>","category_id":{"id":317,"is_a":["meta","category"],"name":"developerguide","title":"Developer guide","uri":"https:\/\/zotonic.com\/id\/developerguide"},"content_group_id":{"id":339,"is_a":["meta","content_group"],"name":"default_content_group","title":{"_type":"trans","tr":{"en":"Default Content Group"}},"uri":"https:\/\/zotonic.com\/id\/default_content_group"},"created":"2020-05-30T05:47:25Z","creator_id":{"id":336,"is_a":["person","robot"],"name":"gitbot","title":"Git","uri":"https:\/\/zotonic.com\/id\/336"},"github_url":"https:\/\/github.com\/zotonic\/zotonic\/tree\/master\/doc\/developer-guide\/controllers.rst","is_authoritative":true,"is_dependent":false,"is_featured":false,"is_protected":false,"is_published":true,"is_unfindable":false,"language":["en"],"modified":"2022-02-15T10:01:23Z","modifier_id":{"id":336,"is_a":["person","robot"],"name":"gitbot","title":"Git","uri":"https:\/\/zotonic.com\/id\/336"},"name":"doc_developerguide_controllers","pivot_geocode":null,"pivot_location_lat":null,"pivot_location_lng":null,"privacy":0,"publication_end":"9999-06-01T00:00:00Z","publication_start":"2022-02-15T10:01:23Z","slug":"controllers","title":"Controllers","title_slug":"controllers","tz":"UTC","uri":null,"version":18,"visible_for":0},"uri":"https:\/\/zotonic.com\/id\/1540","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/1540"}},"status":"ok"}