phpdependency-injectionpsr-4pimple

Pimple ArgumentCountError: Too few arguments to function


I'm trying to understand dependency injection, and I in theory, I get it, but, I wanted to make an example just to help me. However, I'm getting the following error

PHP Fatal error:  Uncaught ArgumentCountError: Too few arguments to function Main\Services\UserService::__construct(), 0 passed
in ...

Here's my "main" file, I've called it index.php

<?php 
#index.php
require_once 'vendor/autoload.php';

use Main\Controllers\UserController;
use Main\Services\UserService;
use Main\Models\UserModel;
use Pimple\Container;

$container = new Container;
$container['UserModel'] = function($c) {
    return new UserModel();
};

$container['UserService'] = function ($c) {
    return new UserService($c['UserModel']);
};

$container['UserController'] = function ($c) {
    echo "creating a new UserController\n";

    $aUserService = $c['UserService'];
    return new UserController($aUserService);
};

$myUserService = new $container['UserService'];
$myResult = $myUserService->parseGet();
echo $myResult, PHP_EOL;

Here's the model that's being passed into the service

<?php
# Models/UserModel.php
namespace Main\Models;

class UserModel
{
    private $record;

    public function getRecord()
    {
        return [
            'first_name' => 'Bob',
            'last_name'  => 'Jones',
            'email'      => 'bj@example.com',
            'date_joined' => '11-12-2014',
        ];
    }
}

And, here's the service, which takes the model as it's constructor argument

<?php
namespace Main\Services;

use Main\Models\UserModel;

class UserService
{
    private $userModel;

    public function __construct(UserModel $userModel)
    {
        echo "verifying that the userModel passed in was a valid UserModel\n";
        $this->userModel = $userModel;

         print_r($this->userModel->getRecord());
    }

    public function parseGet()
    {
        $retVal = $this->userModel->getRecord();

        return json_encode($retVal);
    }
}

So, in theory, Pimple should be able to instantiate a UserService object. I even verified that the UserModel passed into the UserService class is a valid UserModel object (which it is as is evident that it prints out an array)

What am I missing? Is there something that I have failed to account for?

Oh, here's the composer.json file

{
    "require": {
        "pimple/pimple": "~3.0"
    },
    "autoload": {
        "psr-4": {
            "Main\\" : "./"
        }
    }
}

I made a gitHub link so the project can be checked out and ran without having to copy past everything (https://github.com/gitKearney/pimple-example)

SOLUTION

The problem was I have an extra new in the line

$myUserService = new $container['UserService'];

It was so obvious, I couldn't see it


Solution

  • $container['UserService'] already is a UserService object. check yer service definition:

    $container['UserService'] = function ($c) {
        return new UserService($c['UserModel']);
    };
    

    That sets $container['UserService'] to be return new UserService($c['UserModel']) when it's invoked, right?

    Your code is basically going:

    $o1 = new UserService($c['UserModel']);
    $o2 = new $o2;