Asked  7 Months ago    Answers:  5   Viewed   44 times

I am starting to look into Laravel but I don't understand the concept of Service Container.

How does it work and what do developers need to know to fully utilize this concept in Laravel?

 Answers

26

The Service Container in Laravel is a Dependency Injection Container and a Registry for the application

The advantages of using a Service Container over creating manually your objects are:

Ability to manage class dependencies on object creation

You define how a object should be created in one point of the application (the binding) and every time you need to create a new instance, you just ask it to the service container, and it will create it for you, along with the required dependencies

For example, instead of creating objects manually with the new keyword:

//every time we need YourClass we should pass the dependency manually
$instance = new YourClass($dependency);

you can register a binding on the Service Container:

//add a binding for the class YourClass 
App::bind( YourClass::class, function()
{
    //do some preliminary work: create the needed dependencies
    $dependency = new DepClass( config('some.value') );

    //create and return the object with his dependencies
    return new YourClass( $dependency );
});

and create an instance through the service container with:

//no need to create the YourClass dependencies, the SC will do that for us!
$instance = App::make( YourClass::class );

Binding of interfaces to concrete classes

With Laravel automatic dependency injection, when an interface is required in some part of the app (i.e. in a controller's constructor), a concrete class is instantiated automatically by the Service Container. Changing the concrete class on the binding, will change the concrete objects instantiated through all your app:

//everityme a UserRepositoryInterface is requested, create an EloquentUserRepository 
App::bind( UserRepositoryInterface::class, EloquentUserRepository::class ); 

//from now on, create a TestUserRepository 
App::bind( UserRepositoryInterface::class, TestUserRepository::class );

Using the Service Container as a Registry

You can create and store unique object instances on the container and get them back later: using the App::instance method to make the binding, and thus using the container as a Registry.

// Create an instance.
$kevin = new User('Kevin');

// Bind it to the service container.
App::instance('the-user', $kevin);

// ...somewhere and/or in another class...

// Get back the instance
$kevin = App::make('the-user'); 

As a final note, essentially the Service Container -is- the Application object: it extends the Container class, getting all the container's funtionalities

Wednesday, March 31, 2021
 
Slinky
answered 7 Months ago
32

First of all, Laravel uses service container and service providers, not server container or server provider :)

Here are some benefits of using dependencies injection (DI):

Simplify the object creation

Because your Test class constructor is quite simple, you don't see the benefit of dependencies injection. Think about a class like this:

class Complex {
    public function __construct(
        FooService $fooService,
        BarService $barService,
        int $configValue
    ) {

    }
}

Without DI, you have to get (or create) instances of $fooService and $barService, retrieve the value of $configValue from the configuration files every time you want a new instance of the Complex class.

With DI, you tell the service container how to create the Complex instance once, then the container can give the correct instance for you with one call (e.g. $container->make(Complex::class))

Manage the couplings between your classes

Continue with the previous example. What happens if the FooService and BarService depends on other classes, too?

Without DI, you have to create instances of the dependent objects (and hope that they do not depends on other classes). This usually ends with multiple instances of one class created, a waste of codes and computer memory.

With DI, all dependent objects are created by the container (you have to register those classes with the container before). The container also manager to keep only one instance of each class if you want, which save the amount of code as well as the amount of memory used by your program.

Only use one instance of your classes when registering with singleton

To keep only one instance of the class in the whole life of the current request, you can register your class creation process with singleton method instead of bind

Wednesday, March 31, 2021
 
Eddas
answered 7 Months ago
73

Try wrapping your routes (inside app/Http/routes.php) in a Route::group() with the web middleware:

Route::group(['middleware' => ['web']], function () {
    // My Routes
});

An easy way to test this:

Route::group(['middleware' => 'web'], function () {
    Route::get('', function () {
        Session::set('test', 'testing');
    });

    Route::get('other', function () {
        dd(Session::get('test'));
    });
});

If you remove the web middleware, you'll receive null since the web middleware is responsible for starting the session.

Ensure you have the web middleware group inside your app/Http/Kernel.php:

protected $middlewareGroups = [
    'web' => [
        MiddlewareEncryptCookies::class,
        IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
        IlluminateSessionMiddlewareStartSession::class,
        IlluminateViewMiddlewareShareErrorsFromSession::class,
        MiddlewareVerifyCsrfToken::class,
    ],
];
Saturday, May 29, 2021
 
exxed
answered 5 Months ago
14

3.5.3 Weak Conformance In some situations Scala uses a more general conformance relation. A type S weakly conforms to a type T , written S <:w T , if S <: T or both S and T are primitive number types and S precedes T in the following ordering.

  • Byte <:w Short
  • Byte <:w Character
  • Short <:w Int
  • Int <:w Long
  • Long <:w Float
  • Float <:w Double

A weak least upper bound is a least upper bound with respect to weak conformance.

Where is this used? For one thing, it determines the type of if expressions:

The type of the conditional expression is the weak least upper bound (§3.5.3) of the types of e2 and e3

In Scala 2.7.x, this would by of type AnyVal, the least uppper bound of Int and Double. In 2.8.x, it types as Double.

scala> if (true) 1 else 1d
res0: Double = 1.0

Similarly:

scala> try { 1 } catch { case _ => 1.0 }
res2: Double = 1.0

scala> (new {}: Any) match { case 1 => 1; case _ => 1.0 }
res6: Double = 1.0

scala> def pf[R](pf: PartialFunction[Any, R]): PartialFunction[Any, R] = pf
pf: [R](pf: PartialFunction[Any,R])PartialFunction[Any,R]

scala> pf { case 1 => 1; case _ => 1d }
res4: PartialFunction[Any,Double] = <function1>

Another place it is used is in type inference:

scala> def foo[A](a1: A, a2: A): A = a1
foo: [A](a1: A,a2: A)A

scala> foo(1, 1d)
res8: Double = 1.0

scala> def foos[A](as: A*): A = as.head
foos: [A](as: A*)A

scala> foos(1, 1d)
res9: Double = 1.0

And also for simple numeric widening:

Numeric Widening. If e has a primitive number type which weakly conforms (§3.5.3) to the expected type, it is widened to the expected type using one of the 6.26 Implicit Conversions 97 numeric conversion methods toShort, toChar, toInt, toLong, toFloat, toDouble defined in §12.2.1. expected type is a primitive numeric type Byte, Short or Char, and the expression e is an integer literal fitting in the range of that type, it is converted to the same literal in that type.

scala> 1: Double
res10: Double = 1.0

UPDATE

As pointed out by Daniel, the spec is wrong about which types have weak conformance. Let's ask the compiler itself:

scala> :power
** Power User mode enabled - BEEP BOOP      **
** scala.tools.nsc._ has been imported      **
** New vals! Try repl, global, power        **
** New cmds! :help to discover them         **
** New defs! Type power.<tab> to reveal     **

scala> settings.maxPrintString = 10000


scala> import global.definitions._
import global.definitions._

scala> (for{c1 <- ScalaValueClasses;
      c2 <- ScalaValueClasses
      isNSC = isNumericSubClass(c1, c2)
      if isNSC
  } yield ("isNumericSubClass (%s, %s) = %b" format (c1, c2, isNSC))).mkString("n")


res5: String =
isNumericSubClass (class Byte, class Byte) = true
isNumericSubClass (class Byte, class Short) = true
isNumericSubClass (class Byte, class Int) = true
isNumericSubClass (class Byte, class Long) = true
isNumericSubClass (class Byte, class Float) = true
isNumericSubClass (class Byte, class Double) = true
isNumericSubClass (class Short, class Short) = true
isNumericSubClass (class Short, class Int) = true
isNumericSubClass (class Short, class Long) = true
isNumericSubClass (class Short, class Float) = true
isNumericSubClass (class Short, class Double) = true
isNumericSubClass (class Int, class Int) = true
isNumericSubClass (class Int, class Long) = true
isNumericSubClass (class Int, class Float) = true
isNumericSubClass (class Int, class Double) = true
isNumericSubClass (class Long, class Long) = true
isNumericSubClass (class Long, class Float) = true
isNumericSubClass (class Long, class Double) = true
isNumericSubClass (class Char, class Int) = true
isNumericSubClass (class Char, class Long) = true
isNumericSubClass (class Char, class Char) = true
isNumericSubClass (class Char, class Float) = true
isNumericSubClass (class Char, class Double) = true
isNumericSubClass (class Float, class Float) = true
isNumericSubClass (class Float, class Double) = true
isNumericSubClass (class Double, class Double) = true
Monday, August 9, 2021
 
godot
answered 3 Months ago
67

It's missing ::class I had the same problem, just like you, one little mistake.

Sunday, August 29, 2021
 
kamikaze_pilot
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share