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
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
namespace Example\HelloWorld;
namespace Example\Controllers;
class HelloWorldPresenter
class Homepage
{
public function helloWorld()
public function show()
{
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
return [
['GET', '/hello-world', [
'Example\HelloWorld\HelloWorldPresenter',
'helloWorld',
]],
['GET', '/', ['Example\Controllers\Homepage', 'show']],
];
```
@ -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.
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)

View file

@ -2,22 +2,22 @@
### 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).
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
namespace Example\HelloWorld;
namespace Example\Controller;
use Http\Response;
class HelloWorldPresenter
class Homepage
{
private $response;
@ -26,14 +26,14 @@ class HelloWorldPresenter
$this->response = $response;
}
public function hello()
public function show()
{
$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.

View file

@ -60,17 +60,17 @@ $class->$method($vars);
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
namespace Example\HelloWorld;
namespace Example\Controllers;
use Http\Request;
use Http\Response;
class HelloWorldPresenter
class Homepage
{
private $request;
private $response;
@ -81,7 +81,7 @@ class HelloWorldPresenter
$this->response = $response;
}
public function hello()
public function show()
{
$content = '<h1>Hello World</h1>';
$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.

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');`
Now in your `HelloWorldPresenter`, add the new dependency like this:
Now in your `Homepage` controller, add the new dependency like this:
```php
<?php
namespace Example\HelloWorld;
namespace Example\Controllers;
use Http\Request;
use Http\Response;
use Example\Template\Engine as TemplateEngine;
class HelloWorldPresenter
class Homepage
{
private $request;
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.
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
public function hello()
public function show()
{
$data = [
'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>
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.