Chapter 5 of the Learn PHP 8 from scratch track

Every article gets its address

9 exercises · 1,250 XP · about 3 h

This chapter works on: composer requireDependencyvendor/ComposerRouterStatic methodSeparation of concernsuseAnonymous functionAssociative arrayisset()Front controllerClass constant$_SERVERRoute parameterLinkMethodEnumfrom()HTTP status codes404405http_response_codetryFrom()ExceptionthrowtrycatchInheritanceextendsparent::Custom exception

The chapter's exercises

  1. Installing a router

    Exercise 1 · 100 XP · 3 objectives checked by tests

    The gazette has only one page, and Madame Lou would like each article to have its own, with its own address: /articles/the-pumpkin-festival. To match an address to some code, you need a router. You could write one yourself, but others have already done it very well: FastRoute, by Nikita Popov, one of the developers of PHP itself.

    composer requireDependencyvendor/ComposerRouter

  2. The newsroom moves out

    Exercise 2 · 100 XP · 3 objectives checked by tests

    Odette's nephew did some tidying up overnight. The publications now live in src/Contenu/Redaction.php (Redaction: the newsroom), and each article got a slug, its name in addresses: the-pumpkin-festival. The newspaper's header has moved to src/Web/Page.php. He left you a note: “index.php doesn't need to know everything anymore. It asks the newsroom for the publications, and Page for the layout.”

    Static methodSeparation of concernsuse

  3. Functions without a name

    Exercise 3 · 150 XP · 5 objectives checked by tests

    Madame Lou has big plans: one page per article, one page per section, a form for classified ads… All these addresses will land in the same public/index.php. So she needs a way to choose what to display depending on the requested address. Before calling in a tool to the rescue, let's build it by hand, with anonymous functions.

    Anonymous functionAssociative arrayisset()Router

  4. The front controller

    Exercise 4 · 150 XP · 5 objectives checked by tests

    Your $pages array works, but Madame Lou is already looking further ahead: /articles/the-pumpkin-festival, /articles/the-mayors-cat-is-missing… One line per article, by hand, would never end. The router you installed earlier, FastRoute, can recognize whole families of addresses. For now, it will simply replace your array, without changing anything on the front page.

    RouterFront controllerClass constant$_SERVER

  5. One page per article

    Exercise 5 · 150 XP · 4 objectives checked by tests

    On the front page, you only read the beginning of each article. The villagers want the rest! Each article will get its own page, at the address /articles/ followed by its slug.

    Route parameterLinkMethod

  6. Sections online

    Exercise 6 · 150 XP · 3 objectives checked by tests

    Gaston only reads the weather, and Odette only reads the village fair. Each section will get its own page: /sections/weather, /sections/village-fair, /sections/news-in-brief. The name in the address is the value of the Rubrique (section) enum, the one you gave it in chapter 2.

    Route parameterEnumfrom()

  7. Lost in the post

    Exercise 7 · 150 XP · 5 objectives checked by tests

    Léo, the mayor's grandson, has fun typing anything at all in the address bar: /articles/the-mayor-won-the-lottery, /sections/sport… The gazette answers with a blank page, or crashes. A real website answers “this page does not exist”, with the matching HTTP status code, so that browsers and search engines understand it too.

    HTTP status codes404405http_response_codetryFrom()

  8. The missing article

    Exercise 8 · 150 XP · 3 objectives checked by tests

    Odette's nephew is preparing a “Gaston's articles” page, and he forgot to test for the null returned by Redaction::article(). The result: Call to a member function versHtmlComplet() on null, an error that shows up far from its cause and doesn't say what is missing. Will every new call to Redaction::article() have to remember the null? No: when the article does not exist, Redaction::article() will throw an exception, and the front controller will catch it, once and for all.

    Exceptionthrowtrycatch

  9. An exception with its own name

    Exercise 9 · 150 XP · 4 objectives checked by tests

    Odette's nephew is worried. The front controller catches every exception: the day the gazette has a database and that database breaks down, readers will see “Lost in the post” instead of a real error, and nobody will go looking for the problem. We need a separate exception that means “this article does not exist”, and we should catch only that one.

    Inheritanceextendsparent::Custom exceptionException