DEV Community

marius-ciclistu
marius-ciclistu

Posted on • Originally published at marius-ciclistu.Medium on

Maravel-Framework’s new di helper


Maravel-Framework new di helper

Maravel resolves the macroable classes from the container instead of instantiating them directly.

This transforms the registration of each macro on each request into registration of each owning class via a child that can also override not just extend the parent functionality. This reduces the registration operations because each macroable class can have multiple macros and also empowers the developer more than the macros do.

The issue was that if app was called before the app finished booting, it would crash the application (it happened to me when I used \app instead of new for all macroable classes because there were a few places where the application was not yet booted, so I had to revert the changes).

Version 10.52.0 of the Maravel-Framework has a new helper for retrieving classes from the container in a safer manner than with the usual app helper, (di) that safely resolves from container a class ONLY if the app has been booted or will instantiate the class without using the container.

This brings an extra layer of safety and avoids crashes for corner cases.

Both Maravel and Maravelith templates have their own helper.

// Maravel
   /**
     * Safely resolve from container a class ONLY after the app has been booted.
     * If not, it will instantiate the classFqn only with $parameters as list
     */
    function di(string $classFqn, array $parametersList = []): mixed
    {
        $container = Container::getInstance();

        if ($container instanceof \Laravel\Lumen\Application && $container->isBooted()) {
            return $container->make($classFqn, $parametersList);
        }

        if (
            \class_exists($classFqn)
            && (
                $parametersList === []
                || \array_values($parametersList) === $parametersList
            )
        ) {
            return new $classFqn(...$parametersList);
        }

        throw new \Illuminate\Contracts\Container\BindingResolutionException(
            'di function called before app booted for: ' . $classFqn . ' trace: ' . \json_encode(
                \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)
            )
        );
    }

// Maravelith
   /**
     * Safely resolve from container a class ONLY after the app has been booted.
     * If not, it will instantiate the classFqn only with $parameters as list
     */
    function di(string $classFqn, array $parametersList = []): mixed
    {
        $container = Container::getInstance();

        if ($container instanceof \Illuminate\Foundation\Application && $container->isBooted()) {
            return $container->make($classFqn, $parametersList);
        }

        if (
            \class_exists($classFqn)
            && (
                $parametersList === []
                || \array_values($parametersList) === $parametersList
            )
        ) {
            return new $classFqn(...$parametersList);
        }

        throw new \Illuminate\Contracts\Container\BindingResolutionException(
            'di function called before app booted for: ' . $classFqn . ' trace: ' . \json_encode(
                \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)
            )
        );
    }
Enter fullscreen mode Exit fullscreen mode

Conclusions

  • Use \app in Lumen/Maravel/Laravel/Maravelith when you want the app/container instance or the instance via class/interface/abstract FQN or alias (or \resolve in Maravelith/Laravel)
  • Use \di in Maravel/Maravelith only when you want to resolve a class FQN, NOT interface/abstract FQN or alias.
  • \app and \resolve support both list and associative array in Maravel/Maravelith for $parametersList parameter while \di supports ONLY list.
  • parameters as list are faster to code and execute.

Top comments (0)