Getting started with Slim PHP framework by building a very simple MVC/OOP app
Tags: webdev, beginners, php, tutorial
Published: 2018-06-29 07:45:27

---
title: Getting started with Slim PHP framework by building a very simple MVC/OOP app
published: true
description: Take your first steps using Slim PHP framework to build a farm!
tags: webdev, beginners, php, tutorial
cover_image: https://maydenacademy.co.uk/wp-content/uploads/2018/05/marcio-motta-560185-unsplash-e1525962602702.jpg
---

*Aim:* 
We are going to build a Slim application that creates a farm pen and outputs the noises that the cow & chicken inside the pen make.

*Requirements:*
	- A pen can only contain a cow and a chicken (will help us practice with slim dependancy injection container)
	- Must implement an MVC approach (help us understand how models, views and controllers work together)

**1.** So we are gonna need the slim skeleton application - open your command line and run:```composer create-project slim/slim-skeleton slimFarm```
- if you don’t have composer installed globally use the composer documentation to get it

**2.** On your command line navigate (cd) into slimFarm directory that has been made for you

**3.** We are going to run a php server so we can see that the slim app is present and working 
- In your command line run:```php -S 0.0.0.0:8080 -t ./public/```

**4.** Go to http://0.0.0.0:8080/ to check its working (you should get the slim default page)

**5.** Open files in your text editor and make a Classes folder inside src

**6.** Add your namespace to autoloading in composer.json:
```json
"autoload": {
  "psr-4": {
    "Farm\\": "src/classes/"
  }
},
```
- n.b: this is in addition to the already existing autoload-dev

- This will mean we can reference our classes using namespaces rather than having loads of require's everywhere.

**7.** Open a new tab in your command line and run `composer dump-autoload` in the command line
- This regenerates our autoloading and namespaces to contain the changes we just made in step 6.

**8.** We need our Cow and Chickens to go in the pen! so make our classes inside Classes/Models folder:
```php
namespace Farm\Models;

class ChickenModel
{
    public $speak = 'cluck';
}
```

```php
namespace Farm\Models;

class CowModel
{
    public $speak = 'moo';
}
```

**9.** Create a Pen class inside Classes/Models folder:
namespace Farm\Models;
```php
class PenModel
{
    public $cow;
    public $chicken;

    public function __construct($cow, $chicken)
    {
        $this->cow = $cow;
        $this->chicken = $chicken;
    }

    public function getCowNoise(){
        return $this->cow->speak;
    }

    public function getChickenNoise(){
        return $this->chicken->speak;
    }
}
```

**10.** Lets make a factory so that Pen can be created quickly with its dependencies in just one call.
- Make a Factories folder (inside the Classes folder)
- Make PenModelFactory:
```php
namespace Farm\Factories;

class PenModelFactory
{
    function __invoke()
    {
        $cow = new \Farm\Models\CowModel();
        $chicken = new \Farm\Models\ChickenModel();
        return new \Farm\Models\PenModel($cow, $chicken);
    }
}
```
- Our factory doesn't need a constructor function, the logic is put inside the __invoke magic method because of the way it is called from our Dependency Injection Container (DIC) 

**11.** So now we have made our factory let's put it in our DIC
- Think of the DIC as a big associative array that knows how to instantiate objects for you we put in there for use later in our application
- Open up src/dependancies.php
- There are preexisting things inside the DIC already
- Add our factory like this:
```php
$container['penModel'] = new \Farm\Factories\PenModelFactory();
```
- We are saying "inside our container (DIC) add a new key of 'penModel' and when we ask for that 'penModel' run our factory to instantiate and return a ready made pen object with all the dependencies (cow + chicken) taken care of."

**12.** Let’s look in our routing file to see how we deal with different HTTP Requests to our application.
- Like the defaults already written in here we could use quick anonymous functions to save having to create a factory but we instead are gonna "do it right" so we will make a route and use a controller to call our business logic.
- Delete the existing $app->get(.....) routes already in the file (we will create our own)
- Set up our route:
```php
$app->get('/makeMeAPen', <where our callback will go> );
```
- /makeMeAPen is the URL extension people are expecting to visit to run our code
- But we don't have a controller yet so....

**13.** Let’s make a controller to call our PenFactory and render out a view:
- Create a Controllers directory inside src/Classes
- Create PenController inside src/Classes/Controllers/
```php
namespace Farm\Controllers;

class PenController
{
    protected $container;

    //this constructor passes the DIC in so we can get our PenFactory out of it later
    function __construct($container)
    {
        $this->container = $container;
    }

    function __invoke($request, $response, $args)
    {
        //create our pen from Penfactory in DIC
        $pen = $this->container->get('penModel');

        //assign args (variables that will be available on rendered view)
        $args['cowNoise'] = $pen->getCowNoise();
        $args['chickenNoise'] = $pen->getChickenNoise();

        //get the default template renderer out of DIC and pass the response and $args to a template file
        return $this->container->get('renderer')->render($response, 'showFarm.phtml', $args);
    }
}
```

**14.** Now our controller exists lets add it in as the thing that happens when our route is hit:
```php
$app->get('/makeMeAPen', \Farm\Controllers\PenController::class);
```

**15.** Notice in our PenController we are calling a template file that doesn't exist yet so lets create it:
- Create showFarm.phtml in /templates folder
- Use the values you put into the $args associative array as normal variables:
```php
<!DOCTYPE html>
<html>
    <head>
        <title>slimFarm</title>
        <style>
            h2 {
                font-size: 10rem;
                color: red;
            }
        </style>
    </head>
    <body>
            <h2>Cows go: <?php echo htmlspecialchars($cowNoise); ?>!</h2>
            <h2>Chickens go: <?php echo htmlspecialchars($chickenNoise); ?>!</h2>
    </body>
</html>
```
**16.** Navigate to http://0.0.0.0:8080/makeMeAPen and behold the brilliance of your super advanced app!