routing.rst 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. Routing
  2. #######
  3. Elgg has two mechanisms to respond to HTTP requests that don't already go through the
  4. :doc:`/design/actions` and :doc:`/guides/views/simplecache` systems.
  5. URL Identifier and Segments
  6. ===========================
  7. After removing the site URL, Elgg splits the URL path by ``/`` into an array. The first
  8. element, the **identifier**, is shifted off, and the remaining elements are called the
  9. **segments**. For example, if the site URL is ``http://example.com/elgg/``, the URL
  10. ``http://example.com/elgg/blog/owner/jane?foo=123`` produces:
  11. Identifier: ``'blog'``. Segments: ``['owner', 'jane']``. (the query string parameters are
  12. available via ``get_input()``)
  13. The site URL (home page) is a special case that produces an empty string identifier and
  14. an empty segments array.
  15. Page Handler
  16. ============
  17. To handle all URLs that begin with a particular identifier, you can register a function to
  18. act as a :doc:`/guides/pagehandler`. When the handler is called, the segments array is
  19. passed in as the first argument.
  20. The following code registers a page handler for "blog" URLs and shows how one might route
  21. the request to a resource view.
  22. .. code:: php
  23. elgg_register_page_handler('blog', 'blog_page_handler');
  24. function blog_page_handler(array $segments) {
  25. // if the URL is http://example.com/elgg/blog/view/123/my-blog-post
  26. // $segments contains: ['view', '123', 'my-blog-post']
  27. $subpage = elgg_extract(0, $segments);
  28. if ($subpage === 'view') {
  29. // use a view for the page logic to allow other plugins to easily change it
  30. set_input('guid', (int)elgg_extract(1, $segments));
  31. echo elgg_view('resources/blog/view');
  32. // in page handlers, return true says, "we've handled this request"
  33. return true;
  34. }
  35. // ... handle other subpages
  36. }
  37. The ``route`` Plugin Hook
  38. =========================
  39. The ``route`` plugin hook is triggered earlier, before page handlers are called. The URL
  40. identifier is given as the type of the hook. This hook can be used to modify the identifier
  41. or segments, to take over page rendering completely, or just to add some logic before the
  42. request is handled elsewhere.
  43. Generally devs should use a page handler unless they need to affect a single page or a wider variety of URLs.
  44. The following code intercepts requests to the page handler for ``customblog`` and internally redirects them
  45. to the ``blog`` page handler.
  46. .. code:: php
  47. function myplugin_customblog_route_handler($hook, $type, $returnvalue, $params) {
  48. // direct Elgg to use the page handler for 'blog'
  49. $returnvalue['identifier'] = 'blog';
  50. return $returnvalue;
  51. }
  52. elgg_register_plugin_hook_handler('route', 'customblog', 'myplugin_customblog_route_handler');
  53. The following code results in ``/blog/all`` requests being completely handled by the plugin hook handler.
  54. For these requests the ``blog`` page handler is never called.
  55. .. code:: php
  56. function myplugin_blog_all_handler($hook, $type, $returnvalue, $params) {
  57. $segments = elgg_extract('segments', $returnvalue, array());
  58. if (isset($segments[0]) && $segments[0] === 'all') {
  59. $title = "We're taking over!";
  60. $content = elgg_view_layout('one_column', array(
  61. 'title' => $title,
  62. 'content' => "We can take over page rendering completely"
  63. ));
  64. echo elgg_view_page($title, $content);
  65. // in the route hook, return false says, "stop rendering, we've handled this request"
  66. return false;
  67. }
  68. }
  69. elgg_register_plugin_hook_handler('route', 'blog', 'myplugin_blog_all_handler');
  70. Routing overview
  71. ================
  72. For regular pages, Elgg's program flow is something like this:
  73. #. A user requests ``http://example.com/blog/owner/jane``.
  74. #. Plugins are initialized.
  75. #. Elgg parses the URL to identifier ``blog`` and segments ``['owner', 'jane']``.
  76. #. Elgg triggers the plugin hook ``route, blog`` (see above).
  77. #. Elgg finds a registered page handler (see above) for ``blog``, and calls the function, passing in
  78. the segments.
  79. #. The page handler function determines it needs to render a single user's blog. It stores the username
  80. via ``set_input()`` and calls the view ``resources/blog/owner``.
  81. #. The ``resources/blog/owner`` view gets the username via ``get_input()``, and uses many other views and
  82. formatting functions like ``elgg_view_layout()`` and ``elgg_view_page()`` to create the entire HTML page.
  83. #. The page handler echos the view HTML and returns ``true`` to indicate it handled the request.
  84. #. PHP invokes Elgg's shutdown sequence.
  85. #. The user receives a fully rendered page.
  86. Elgg's coding standards suggest a particular URL layout, but there is no syntax enforced.