Skip to content

Commit

Permalink
doc: Add custom controllers cookbook chapter (#1565)
Browse files Browse the repository at this point in the history
  • Loading branch information
ddeboer committed Jan 2, 2017
1 parent 2ef9945 commit b847437
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
108 changes: 108 additions & 0 deletions doc/cookbook/custom-controller.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
.. _cookbook-custom-controller:

Create a custom controller
==========================

Zotonic comes with a large collection :ref:`controllers <guide-controllers>`
that cover many use cases, so you’ll probably have to resort to custom
controllers less often than you may be used to from other web frameworks. Still,
the time may come when you need to process HTTP requests in your own way.

You can do so by creating a custom :ref:`controller <guide-controllers>`. Create
a module in your site’s :file:`controllers/` directory and prefix it with
``controller_``:

.. code-block:: erlang
:caption: yoursite/controllers/controller_say_hello.erl
-module(controller_say_hello).
-export([
html/1
]).
%% Include this to have a working controller out of the box
-include_lib("controller_html_helper.hrl").
%% This function renders some HTML when the controller is called
html(Context) ->
{<<"Hello world and all the people in it!">>, Context}.
To be able to handle HTTP requests with this controller, you need to
:ref:`define a dispatch rule <defining-dispatch-rules>` that maps some request
URL to this controller:

.. code-block:: erlang
:caption: yoursite/dispatch/dispatch
[
{say_hello, ["hello"], controller_say_hello, []}
].
Now, if you go to ``http://yoursite.com/hello`` in your browser, you will see
the output of the ``controller_say_hello`` controller.

Handling POST requests
----------------------

Now you’ve seen how to handle GET requests, let’s turn to POST requests. First,
your controller must show that it can handle POSTs. You do so by adding an
``allowed_methods/2`` function:

.. code-block:: erlang
:caption: yoursite/controllers/controller_say_hello.erl
-module(controller_say_hello).
-export([
%% ...
allowed_methods/2
]).
%% ...
%% This controller will handle only GETs and POSTs
allowed_methods(ReqData, State) ->
{['GET', 'POST'], ReqData, State}.
A ``process_post/2`` function will be called with the POST data, so define it:

.. code-block:: erlang
:caption: yoursite/controllers/controller_say_hello.erl
-module(controller_say_hello).
-export([
allowed_methods/2,
html/1,
process_post/2,
]).
-include_lib("controller_html_helper.hrl").
allowed_methods(ReqData, State) ->
{['GET', 'POST'], ReqData, State}.
html(Context) ->
{<<"Hello world and all the people in it!">>, Context}.
process_post(ReqData, Context) ->
%% Process the POST data
Context1 = ?WM_REQ(ReqData, Context),
Context2 = z_context:ensure_qs(Context1),
Name = list_to_binary(z_context:get_q(name, Context2)),
{{halt, 200}, wrq:set_resp_body(<<"Thank you posting, ", Name/binary>>, ReqData), Context}.
Try it out on the command line:

.. code-block:: shell
$ curl -v -X POST -d 'name=David' http://yoursite.dev/hello
# prints:
Thank you posting, David
.. seealso::

* :ref:`guide-controllers` in the Developer Guide
1 change: 1 addition & 0 deletions doc/cookbook/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Cookbooks
:maxdepth: 1

custom-action
custom-controller
custom-model
custom-pivot
custom-tag
Expand Down
2 changes: 2 additions & 0 deletions doc/developer-guide/controllers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ The `Webmachine documentation
<http://wiki.basho.com/Webmachine-Demo.html>`_ itself is also very
helpful for understanding controllers.

.. seealso:: :ref:`cookbook-custom-controller`

.. _guide-controllers-webzmachine:

Differences between Zotonic’s and Basho’s Webmachine
Expand Down
1 change: 1 addition & 0 deletions doc/developer-guide/dispatch-rules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ When an URL is requested by the web browser, the dispatch system looks
at that URL and matches it agains all dispatch rules that are
loaded. Based on the match, it will call a :ref:`controller <controllers>` to handle the request.

.. _defining-dispatch-rules:

Defining dispatch rules
-----------------------
Expand Down

0 comments on commit b847437

Please sign in to comment.