Hi!
I’ve been trying to get the twig/view templating system to work on my new slim app. I got twig to work with the non-container based set up provided on the Twig-View github page for slim, but I figured I’d try to familiarize myself with how containers and dependency injection works. For some reason, though, I cannot for the life of me get the container example work. The error I get is:
Fatal error: Uncaught ArgumentCountError: Too few arguments to function DI\Container::__construct(), 0 passed in /var/www/html/mysite/public_html/index.php on line 16 and at least 2 expected in /var/www/html/mysite/vendor/php-di/php-di/src/DI/Container.php:77 Stack
I understand that php interpreter is complaining because I’m not passing in arguments to Container(), but I’m not sure what I should pass into Container as I’m initializing it because the tutorial/examples I’ve looked at never pass anything in. Is there some major misunderstanding I’m having regarding how this is supposed to work? Any help in understanding this would be greatly appreciated!
Example code from github for convenience:
use DI\Container;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
require __DIR__ . '/vendor/autoload.php';
// Create Container
$container = new Container();
AppFactory::setContainer($container);
// Set view in Container
$container->set('view', function() {
return Twig::create('path/to/templates', ['cache' => 'path/to/cache']);
});
// Create App
$app = AppFactory::create();
// Add Twig-View Middleware
$app->add(TwigMiddleware::createFromContainer($app));
// Define named route
$app->get('/hello/{name}', function ($request, $response, $args) {
return $this->get('view')->render($response, 'profile.html', [
'name' => $args['name']
]);
})->setName('profile');
// Render from string
$app->get('/hi/{name}', function ($request, $response, $args) {
$str = $this->get('view')->fetchFromString(
'<p>Hi, my name is {{ name }}.</p>',
[
'name' => $args['name']
]
);
$response->getBody()->write($str);
return $response;
});
// Run app
$app->run();
assuming you use PhpDI, try to require from your front controller (index.php) this example of a bootstrap file: (or put it directly in index.php, after require '../vendor/autoload.php';
)
bootstrap.php
<?php
declare(strict_types=1);
use DI\ContainerBuilder;
use Psr\Log\LoggerInterface;
use Slim\App;
try {
$builder = new ContainerBuilder();
$builder->useAutowiring(true);
$definitions = array_merge(
require './../config/settings/settings.php',
require './../config/dependencies/dependencies.php'
);
$builder->addDefinitions($definitions);
$container = $builder->build();
$app = $container->get(App::class);
require './../bootstrap/middleware.php';
require './../bootstrap/routes.php';
$app->run();
} catch (Throwable $t) {
}
Thanks for the response!
I tried adding a bootstrap.php file with the code example you provided, but I didn’t yet have a settings.php or any of the other files your code example requires, so I made some dummy ones to see if that would work and it still produces the same error as before. I hadn’t read much about structuring files like this. Is it necessary to get the Container to run? Could you point in the direction of some documentation about best/required practices related to bootstrapping that might help me understand what’s going on?
How can you have the same error with my code if there is nothing like:
DI\Container::__construct();
???
Just make your index.php like:
<?php
declare(strict_types=1);
require '../vendor/autoload.php';
require './../bootstrap/bootstrap.php';
with a folder structure:
public
index.php
bootstrap
bootstrap.php
routes.php
config
settings
settings.php
dependencies
dependencies.php
vendor
and there is no way, it throws any kind of exception you mentioned.
Of course you can make any folder structure you want, if you don’t wish to have any values in settings.php just remove and leave only dependencies.php. It’s totally up to you.
In relation to best bootstrapping practices, there is not such a thing. It depends on your personal preferences, your application and your perspective as a developer.
In my case, I prefer to split the scope of bootstraping container, middlewares and routes declarations in separate files, apart of index.php. If you do everything at the begining in index.php, nobody is going to condemn you, but I can assure you after some time you will start to create your own, the most suitable folder structure for you.