changed to controllers

This commit is contained in:
Patrick 2014-11-30 21:06:11 +01:00
parent d51b44c6d9
commit 87b4cf3a76
4 changed files with 28 additions and 29 deletions

View file

@ -2,20 +2,22 @@
### Dispatching to a Class ### Dispatching to a Class
In this tutorial we won't implement [MVC (Model-View-Controller)](http://martinfowler.com/eaaCatalog/modelViewController.html). MVC can't be implemented properly in PHP anyway, at least not in the way it was originally conceived. So forget about MVC and instead let's worry about [separation of concerns](http://en.wikipedia.org/wiki/Separation_of_concerns). In this tutorial we won't implement [MVC (Model-View-Controller)](http://martinfowler.com/eaaCatalog/modelViewController.html). MVC can't be implemented properly in PHP anyway, at least not in the way it was originally conceived. If you want to learn more about this, read [A Beginner's Guide To MVC](http://blog.ircmaxell.com/2014/11/a-beginners-guide-to-mvc-for-web.html) and the followup posts.
Instead of just calling everything a controller, let's give our names descriptive names that describe what the class actually does. In this case, we will just display content, so a fitting name would be `Presenter`. If the class does something else, we will name it accordingly. So forget about MVC and instead let's worry about [separation of concerns](http://en.wikipedia.org/wiki/Separation_of_concerns).
Create a new folder inside the `src/` folder with the name `HelloWorld`. This will be where all your hello world related code will end up in. In there, create `HelloWorldPresenter.php`. We will need a descriptive name for the classes that handle the requests. For this tutorial I will use `Controllers` because that will be familiar for the people coming from a framework background. You could also name them `Handlers`.
Create a new folder inside the `src/` folder with the name `Controllers`.In this folder we will place all our controller classes. In there, create a `Homepage.php` file.
```php ```php
<?php <?php
namespace Example\HelloWorld; namespace Example\Controllers;
class HelloWorldPresenter class Homepage
{ {
public function helloWorld() public function show()
{ {
echo 'Hello World'; echo 'Hello World';
} }
@ -28,10 +30,7 @@ Now let's change the hello world route so that it calls your new class method in
```php ```php
return [ return [
['GET', '/hello-world', [ ['GET', '/', ['Example\Controllers\Homepage', 'show']],
'Example\HelloWorld\HelloWorldPresenter',
'helloWorld',
]],
]; ];
``` ```
@ -52,6 +51,6 @@ case \FastRoute\Dispatcher::FOUND:
So instead of just calling a method you are now instantiating an object and then calling the method on it. So instead of just calling a method you are now instantiating an object and then calling the method on it.
Now if you visit `http://localhost:8000/hello-world` everything should work. If not, go back and debug. And of course don't forget to commit your changes. Now if you visit `http://localhost:8000/` everything should work. If not, go back and debug. And of course don't forget to commit your changes.
[<< previous](5-router.md) | [next >>](7-inversion-of-control.md) [<< previous](5-router.md) | [next >>](7-inversion-of-control.md)

View file

@ -2,22 +2,22 @@
### Inversion of Control ### Inversion of Control
In the last part you have set up a presenter class and generated output with `echo`. But let's not forget that you have a nice object oriented HTTP abstraction available. But right now it's not accessible inside your class. In the last part you have set up a controller class and generated output with `echo`. But let's not forget that you have a nice object oriented HTTP abstraction available. But right now it's not accessible inside your class.
The sane option is to use [inversion of control](http://en.wikipedia.org/wiki/Inversion_of_control). This means that instead of giving the class the responsiblity of creating the object it needs, you just ask for them. This is done with [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection). The sane option is to use [inversion of control](http://en.wikipedia.org/wiki/Inversion_of_control). This means that instead of giving the class the responsiblity of creating the object it needs, you just ask for them. This is done with [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection).
If it sounds a little complicated right now, don't worry. Just follow the tutorial and once you see how it is implemented things will make more sense. If it sounds a little complicated right now, don't worry. Just follow the tutorial and once you see how it is implemented things will make more sense.
Change your `HelloWorldPresenter` to the following: Change your `Homepage` controller to the following:
```php ```php
<?php <?php
namespace Example\HelloWorld; namespace Example\Controller;
use Http\Response; use Http\Response;
class HelloWorldPresenter class Homepage
{ {
private $response; private $response;
@ -26,14 +26,14 @@ class HelloWorldPresenter
$this->response = $response; $this->response = $response;
} }
public function hello() public function show()
{ {
$this->response->setContent('Hello World'); $this->response->setContent('Hello World');
} }
} }
``` ```
Please note that you are [importing](http://php.net/manual/en/language.namespaces.importing.php) `Http\Response` at the top of the file. This means that whenever you use `Response` inside this file, it will resolve to the fully qualified name. Note that you are [importing](http://php.net/manual/en/language.namespaces.importing.php) `Http\Response` at the top of the file. This means that whenever you use `Response` inside this file, it will resolve to the fully qualified name.
In the contructor you are now explicitly asking for a `Http\Response`. In this case, `Http\Response` is an interface. So any class that implements the interface can be injected. See [type hinting](http://php.net/manual/en/language.oop5.typehinting.php) and [interfaces](http://php.net/manual/en/language.oop5.interfaces.php) for reference. In the contructor you are now explicitly asking for a `Http\Response`. In this case, `Http\Response` is an interface. So any class that implements the interface can be injected. See [type hinting](http://php.net/manual/en/language.oop5.typehinting.php) and [interfaces](http://php.net/manual/en/language.oop5.interfaces.php) for reference.

View file

@ -60,17 +60,17 @@ $class->$method($vars);
Now all your controller constructor dependencies will be automatically resolved with Auryn. Now all your controller constructor dependencies will be automatically resolved with Auryn.
Go back to your `HelloWorldPresenter.php` and change it to the following: Go back to your `Homepage` controller and change it to the following:
```php ```php
<?php <?php
namespace Example\HelloWorld; namespace Example\Controllers;
use Http\Request; use Http\Request;
use Http\Response; use Http\Response;
class HelloWorldPresenter class Homepage
{ {
private $request; private $request;
private $response; private $response;
@ -81,7 +81,7 @@ class HelloWorldPresenter
$this->response = $response; $this->response = $response;
} }
public function hello() public function show()
{ {
$content = '<h1>Hello World</h1>'; $content = '<h1>Hello World</h1>';
$content .= 'Hello ' . $this->request->getParameter('name', 'stranger'); $content .= 'Hello ' . $this->request->getParameter('name', 'stranger');
@ -90,7 +90,7 @@ class HelloWorldPresenter
} }
``` ```
As you can see now the class has two dependencies. Try to access the page with a GET parameter like this `http://localhost:8000/hello-world?name=Arthur%20Dent`. As you can see now the class has two dependencies. Try to access the page with a GET parameter like this `http://localhost:8000/?name=Arthur%20Dent`.
Congratulations, you have now successfully laid the groundwork for your application. Congratulations, you have now successfully laid the groundwork for your application.

View file

@ -68,18 +68,18 @@ Of course we also have to add a definition in our `Dependencies.php` file becaus
`$injector->alias('Example\Template\Engine', 'Example\Template\MustacheEngineAdapter');` `$injector->alias('Example\Template\Engine', 'Example\Template\MustacheEngineAdapter');`
Now in your `HelloWorldPresenter`, add the new dependency like this: Now in your `Homepage` controller, add the new dependency like this:
```php ```php
<?php <?php
namespace Example\HelloWorld; namespace Example\Controllers;
use Http\Request; use Http\Request;
use Http\Response; use Http\Response;
use Example\Template\Engine as TemplateEngine; use Example\Template\Engine as TemplateEngine;
class HelloWorldPresenter class Homepage
{ {
private $request; private $request;
private $response; private $response;
@ -100,10 +100,10 @@ class HelloWorldPresenter
As you can see I imported the engine with an alias. Without the full namespace it would be relatively unclear what a class does if it is just referenced by `Engine`. Also, another part of the application might also have a class with the name `Engine`. So to avoid that I give it a short and descriptive alias. As you can see I imported the engine with an alias. Without the full namespace it would be relatively unclear what a class does if it is just referenced by `Engine`. Also, another part of the application might also have a class with the name `Engine`. So to avoid that I give it a short and descriptive alias.
We also have to rewrite the `hello` method. Please note that while we are just passing in a simple array, Mustache also gives you the option to pass in a view context object. We will go over this later, for now let's keep it as simple as possible. We also have to rewrite the `show` method. Please note that while we are just passing in a simple array, Mustache also gives you the option to pass in a view context object. We will go over this later, for now let's keep it as simple as possible.
```php ```php
public function hello() public function show()
{ {
$data = [ $data = [
'name' => $this->request->getParameter('name', 'stranger'), 'name' => $this->request->getParameter('name', 'stranger'),
@ -125,14 +125,14 @@ $injector->define('Mustache_Engine', [
]); ]);
``` ```
In your project root folder, create a `templates` folder. In there, create a folder `HelloWorld` and in there a file `Hello.mustache`. The content of the file should look like this: In your project root folder, create a `templates` folder. In there, create a file `Homepage.mustache`. The content of the file should look like this:
``` ```
<h1>Hello World</h1> <h1>Hello World</h1>
Hello {{ name }} Hello {{ name }}
``` ```
Now you can go back to your `HelloWorldPresenter` and change the render line to `$content = $this->templateEngine->render('HelloWorld/Hello', $data);` Now you can go back to your `Homepage` controller and change the render line to `$content = $this->templateEngine->render('Homepage', $data);`
Navigate to the hello page in your browser to make sure everything works. And as always, don't forget to commit your changes. Navigate to the hello page in your browser to make sure everything works. And as always, don't forget to commit your changes.