New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.4] Add support for binding methods to the container #16800

Merged
merged 3 commits into from Dec 14, 2016

Conversation

Projects
None yet
4 participants
@adamwathan
Member

adamwathan commented Dec 14, 2016

Adds support for manually controlling how a method should be called when invoked with Container::call:

$this->app->bindMethod('App\Jobs\SomeJob@handle', function ($job, $app) {
    return $job->handle('foo', 'bar');
});

Prior to this, it was impossible to have parameters in the handle method of a job that could not be auto-resolved by the container, because there was no way to manually control what the parameters should be.

This means you are forced to use type hints for object parameters and have no ability to use primitives as parameters, or have to use the old undocumented job syntax where dependencies were passed to the constructor instead of to the handle method.

For example, it is currently impossible to write a job class like this, where the handle method has dependencies that can't be autoresolved:

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;

class AddCollaboratorToGitHubRepoJob implements ShouldQueue
{
    use Queueable;

    private $user;

    public function __construct($user)
    {
        $this->user = $user;
    }

    public function handle($githubOwner, $githubRepo, $githubToken)
    {
        (new Client)->put($this->collaboratorUrl($githubOwner, $githubRepo), [
            'headers' => ['Authorization' => "token {$githubToken}"],
            'json' => ['permission' => 'pull']
        ]);
    }

    private function collaboratorUrl($owner, repo)
    {
        return "https://api.github.com/repos/{$owner}/{$repo}/collaborators/{$this->user->github_username}";
    }
}

Using the functionality added in this PR, you could specify how handle should be called:

$this->app->bindMethod('App\Jobs\AddCollaboratorToGitHubRepoJob@handle', function ($job, $app) {
    return $job->handle(
        config('services.github.owner'),
        config('services.github.repo'),
        config('services.github.token')
    );
});

This PR intentionally adds only the minimal functionality needed to subvert this issue, and doesn't make any effort to support the when->needs->give syntax, or passing key => value parameters to optionally override things or any of those fancy more complex features.

Instead, it simply adds support for defining what should happen as a whole, much like you would with a standard container binding:

$this->app->singleton(PaymentGateway::class, function () {
    return new PaymentGateway(config('services.stripe.secret'));
});

Additional functionality like that could be added down the road, or we could simply roll with this forever, because it at least does what's needed to fix what's currently impossible.

@taylorotwell taylorotwell merged commit a153c59 into laravel:master Dec 14, 2016

2 checks passed

continuous-integration/styleci/pr The StyleCI analysis has passed
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@GrahamCampbell GrahamCampbell changed the title from Add support for binding methods to the container to [5.4] Add support for binding methods to the container Dec 15, 2016

@tillkruss

This comment has been minimized.

Member

tillkruss commented Dec 17, 2016

Neat!

@wuquanyao

This comment has been minimized.

wuquanyao commented May 3, 2018

Greate!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment