Controller initialization problem

Hi there!

I’m new to Slim so I’m fighting with errors for a while but this one stopped me and I really need help.

Structure of my app is following:

Slim app
-- app\
---- controllers\
---- models\
---- modules\
------ blog\
-------- controllers\
-------- models\
-------- views\
---- views\
-- logs\
-- public\
-- src\
-- tests\
-- vendor\

To initialize my app controllers to use them in routes etc. I have this in my composer.json

“autoload”: {
“psr-4”: {
“Src\”: “app/”
},
“classmap”: [
“app/”
]
}

And my controllers has namespace Src\Controllers;.

My routing logic is following:

In my src/routes.php I first require app/modules/routes.php where I testing if there are some modules and if they are active. If there is active module present I then require app/modules/blog/routes.php where I declare routes for my module.

But if I declare such a route and let controller of that module to handle it I get “Callable PageController does not exist”.

The PageController is in app/modules/blog/controllers and it has namespace Src\Controllers;.

So I have two questions:

  1. How to initialize modules controllers and models?
  2. Is it possible to have templates on multiple places?

For example, if I would like to have app/views/index.phtml and app/module/blog/views/page/index.phtml and I want to render index of page module so I do something like:

$this->view->render($response, ‘/module/page/index.phtml’, $args);

I would really appriciate all the help!

There’s a few problems.

//...
"autoload": {
    "psr-4": {
        "Src\\": "app"
    }
}
//...

Then run composer dump-autoload

So I updated my composer.json so it now looks like this:

{
    "name": "slim/slim-skeleton",
    "description": "A Slim Framework skeleton application for rapid development",
    "keywords": ["microframework", "rest", "router", "psr7"],
    "homepage": "http://github.com/slimphp/Slim-Skeleton",
    "license": "MIT",
    "authors": [
        {
            "name": "Josh Lockhart",
            "email": "info@joshlockhart.com",
            "homepage": "http://www.joshlockhart.com/"
        }
    ],
    "require": {
        "php": ">=5.5.0",
        "slim/slim": "^3.1",
        "slim/php-view": "^2.0",
        "monolog/monolog": "^1.17",
        "illuminate/database": "~5.1"
    },
    "require-dev": {
        "phpunit/phpunit": ">=4.8 < 6.0"
    },
    "config": {
        "optimize-autoloader": true,
        "process-timeout" : 0
    },
    "autoload": {
        "psr-4": {
            "Src\\": "app"
        }
    },
    "scripts": {
        "start": "php -S localhost:8080 -t public public/index.php",
        "test": "phpunit"
    }

}

And I also ran composer dump-autoload

What’s next?

that should have resolved your isssues :wink:

My src/routes.php

<?php

// Routes

require __DIR__ . '/../app/modules/routes.php';

/*
$app->get('/[{route:.*}]', function (Request $request, Response $response, array $args) {

	// @TODO: Move logic to the RoutesController.
	//$route = explode('/', $request->getAttribute('route'));

    // Sample log message
    $this->logger->info("Slim-Skeleton 'universal' route");

    // Render index view
    return $this->renderer->render($response, 'index.phtml', $args);
});
*/

$app->any('/[{route:.*}]', 'RoutesController');

/*
$app->get('/test', function (Request $request, Response $response, array $args) {
    // Sample log message
    $this->logger->info("Slim-Skeleton '/' route");

    // Render index view
    return $this->renderer->render($response, 'index.phtml', $args);
});
*/

My app/modules/routes.php

<?php

$modules = get_available_modules($app);

foreach ($modules as $module) {
    if (is_module_present($module)) {
        require_once $module . '/routes.php';
    }
}

This will find that the blog module is present and then it calls app/modules/blog/routes.php

<?php

$app->get('/blog', 'PageController:index');

But if I’ll go to http://localhost:8080/blog it will show

Slim Application Error
The application could not run because of the following error:

Details

Type: RuntimeException
Message: Callable PageController does not exist
File: /home/erwin/Work/silvia/vendor/slim/slim/Slim/CallableResolver.php
Line: 90
Trace

#0 /home/erwin/Work/silvia/vendor/slim/slim/Slim/CallableResolver.php(61): Slim\CallableResolver->resolveCallable('PageController', 'index')
#1 /home/erwin/Work/silvia/vendor/slim/slim/Slim/CallableResolverAwareTrait.php(45): Slim\CallableResolver->resolve('PageController:...')
#2 /home/erwin/Work/silvia/vendor/slim/slim/Slim/Route.php(333): Slim\Routable->resolveCallable('PageController:...')
#3 /home/erwin/Work/silvia/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(122): Slim\Route->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#4 /home/erwin/Work/silvia/vendor/slim/slim/Slim/Route.php(316): Slim\Route->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#5 /home/erwin/Work/silvia/vendor/slim/slim/Slim/App.php(476): Slim\Route->run(Object(Slim\Http\Request), Object(Slim\Http\Response))
#6 /home/erwin/Work/silvia/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(122): Slim\App->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#7 /home/erwin/Work/silvia/vendor/slim/slim/Slim/App.php(370): Slim\App->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#8 /home/erwin/Work/silvia/vendor/slim/slim/Slim/App.php(295): Slim\App->process(Object(Slim\Http\Request), Object(Slim\Http\Response))
#9 /home/erwin/Work/silvia/public/index.php(35): Slim\App->run()
#10 {main}

But the PageController exists in app/modules/blog/controllers/PageController.class.php

<?php

namespace Scr\Controllers;

use Slim;
use Slim\Http\Request;
use Slim\Http\Response;
use Monolog;

class PageController
{

    /** @var Slim\Container $container */
    protected $container;

    /** @var Monolog\Logger $logger */
    protected $logger;

    /** @var Slim\Views\PhpRenderer $view  */
    protected $view;

    function __construct(Slim\Container $container) {
        $this->container = $container;
        $this->logger    = $container->logger;
        $this->view      = $container->renderer;

        // Sample log message
        $this->logger->info("Slim-Skeleton '/blog' route");
    }

    function index(Request $request, Response $response, array $args)
    {


        $this->view->render($response, 'index.phtml', $args);
        return $response->withStatus(200);
    }
}

What am I doing wrong?

I would have expected

$app->get('/blog', 'PageController:index');

to be:

$app->get('/blog', \Scr\Controllers\PageController::class . ':index');

Also, you say that PageController is in app/modules/blog/controllers/PageController.class.php. I would have expected it in app/modules/Scr/Controllers/PageController.class.php unless you have some special autoloading going on? If you’re using composer autoloading, then I’d expect to see:

"Scr\\": "app/modules/Scr/"

in the autoload => psr-4 section of composer.json.

@akrabat Thank you very much it works now!