Skip to content

[FEATURE] Add a Dependency Inversion Container Class to Pancake #235

@guibranco

Description

@guibranco

Description:
I would like to add a Dependency Inversion Container class to the Pancake project. This class should be responsible for handling service (class) registrations and resolving these services when needed, following the Dependency Injection (DI) pattern. This will improve modularity and flexibility within the Pancake framework.

The class should support:

  • Service registration.
  • Resolution of services with dependency support.
  • Singleton and transient lifecycles for services.
  • PSR-11

Below is an example of the DIContainer.php file to illustrate the expected implementation:

<?php

namespace GuiBranco\Pancake;

use Psr\Container\ContainerInterface;
use ReflectionClass;

class DIContainer implements ContainerInterface
{
    private array $services = [];
    private array $sharedInstances = [];

    public function has(string $name): bool
    {
        return isset($this->services[$name]);
    }

    public function get(string $name)
    {
        if (!isset($this->services[$name])) {
            throw new \Exception("Service '{$name}' not registered.");
        }

        // TODO:  check for the shared flag here before returning a new instance (like the resolve method already does).

        if (is_callable($this->services[$name])) {
            return $this->services[$name]($this);
        }

        return $this->resolve($this->services[$name]);
    }

    public function register(string $name, callable $resolver, bool $shared = false)
    {
        $this->services[$name] = [
            'resolver' => $resolver,
            'shared' => $shared,
        ];
    }
    
    protected function resolve(string $name)
    {
        if (!isset($this->services[$name])) {
            throw new \Exception("Service '{$name}' not registered.");
        }

        if ($this->services[$name]['shared']) {
            if (!isset($this->sharedInstances[$name])) {
                $this->sharedInstances[$name] = $this->services[$name]['resolver']($this);
            }
            return $this->sharedInstances[$name];
        }

        return $this->services[$name]['resolver']($this);
    }

    public function registerSingleton(string $name, callable $resolver)
    {
        $this->register($name, $resolver, true);
    }

    public function registerTransient(string $name, callable $resolver)
    {
        $this->register($name, $resolver, false);
    }
}

Task Requirements:

  • Implement the Dependency Inversion Container class for service registration and resolution.
  • Ensure that services can be registered as singletons (shared) or transient instances.
  • Automatically resolve dependencies when required.
  • Provide optional constructor parameter support for services that require other dependencies.

Additional Requirements:

  • Provide unit tests to ensure:
    • Services are correctly registered and resolved.
    • Singleton and transient lifecycles work as expected.
    • Dependencies are correctly resolved when registered.
  • Include integration tests to validate the DI container's functionality within the broader Pancake framework.

Acceptance Criteria:

  • The DI container is implemented and supports the required features.
  • Unit and integration tests are provided to verify the container’s behavior.
  • Documentation is updated to include usage examples for registering and resolving services.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestgitautoGitAuto label to trigger the app in a issue.good first issueGood for newcomershacktoberfestParticipation in the Hacktoberfest eventhelp wantedExtra attention is needed♻️ code qualityCode quality-related tasks or issues📝 documentationTasks related to writing or updating documentation🕔 high effortA task that can be completed in a few days🛠 WIPWork in progress🧪 testsTasks related to testing

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions