Cuối cùng sau một vài ngày nghiên cứu và suy nghĩ rất nhiều về cách tiếp cận tốt nhất cho điều này, sử dụng Laravel cuối cùng tôi đã giải quyết.
tôi phải nói rằng đây là đặc biệt khó khăn trong Laravel 5.2
, bởi vì trong phiên bản này phiên middleware chỉ được thực hiện trong các bộ điều khiển được sử dụng trong một lộ trình, có nghĩa là nếu vì một lý do tôi đã sử dụng một bộ điều khiển (không liên kết cho một cuộc rote) và cố gắng để có được quyền truy cập vào phiên nó sẽ không thể được. Vì vậy, bởi vì tôi không thể sử dụng phiên, tôi quyết định sử dụng các tham số URL, ở đây bạn có cách tiếp cận giải pháp, tôi hy vọng một số bạn thấy nó hữu ích.
như vậy, bạn có một giao diện:
interface Service
{
public function execute();
}
Sau đó, một vài hiện thực cho giao diện:
Các dịch vụ một:
class ServiceOne implements Service
{
public function execute()
{
.......
}
}
Các dịch vụ hai.
class ServiceTwo implements Service
{
public function execute()
{
.......
}
}
Bây giờ là phần thú vị: có một bộ điều khiển với một chức năng mà có một sự phụ thuộc với giao diện dịch vụ NHƯNG tôi cần phải giải quyết nó dinamically để ServiceOne hoặc ServiceTwo có trụ sở tại một đầu vào sử dụng. Vì vậy:
Bộ điều khiển
class MyController extends Controller
{
public function index(Service $service, ServiceRequest $request)
{
$service->execute();
.......
}
}
Xin lưu ý rằng ServiceRequest, xác nhận rằng yêu cầu đã có các tham số mà chúng ta cần phải giải quyết phụ thuộc (gọi nó là 'service_name'
)
Bây giờ, trong AppServiceProvider chúng tôi có thể giải quyết sự phụ thuộc theo cách này:
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
}
public function register()
{
//This specific dependency is going to be resolved only if
//the request has the service_name field stablished
if(Request::has('service_name'))
{
//Obtaining the name of the service to be used (class name)
$className = $this->resolveClassName(Request::get('service_name')));
$this->app->bind('Including\The\Namespace\For\Service', $className);
}
}
protected function resolveClassName($className)
{
$resolver = new Resolver($className);
$className = $resolver->resolveDependencyName();
return $className;
}
}
Vì vậy, bây giờ tất cả các trách nhiệm là dành cho lớp Resolver, cl này ass cơ bản sử dụng tham số truyền cho các contructor để trả lại fullname (với không gian tên) của lớp có nghĩa là sẽ được sử dụng như một thực hiện của giao diện dịch vụ:
class Resolver
{
protected $name;
public function __construct($className)
{
$this->name = $className;
}
public function resolveDependencyName()
{
//This is just an example, you can use whatever as 'service_one'
if($this->name === 'service_one')
{
return Full\Namespace\For\Class\Implementation\ServiceOne::class;
}
if($this->name === 'service_two')
{
return Full\Namespace\For\Class\Implementation\ServiceTwo::class;
}
//If none, so whrow an exception because the dependency can not be resolved
throw new ResolverException;
}
}
Vâng, tôi thực sự hy vọng nó giúp cho một số của bạn.
Lời chúc tốt đẹp nhất!
---------- CHỈNH SỬA -----------
Tôi chỉ nhận thấy rằng không nên sử dụng trực tiếp dữ liệu yêu cầu, bên trong container của Laravel, nó thực sự sẽ làm cho một số rắc rối trong dài hạn.
Cách tốt nhất là đăng ký trực tiếp tất cả các trường hợp có thể được hỗ trợ (serviceone và servicetwo) và sau đó giải quyết một trong số chúng trực tiếp từ bộ điều khiển hoặc phần mềm trung gian, sau đó là bộ điều khiển "ai quyết định" sử dụng dịch vụ nào (từ tất cả khả dụng) dựa trên dữ liệu đầu vào từ yêu cầu.
Cuối cùng nó hoạt động giống nhau, nhưng nó sẽ cho phép bạn làm việc một cách tự nhiên hơn.
Tôi phải nói cảm ơn đến rizqi. Người dùng từ kênh câu hỏi của cuộc trò chuyện chật chội của Laravel.
Cá nhân anh ta đã tạo một số vàng article về điều này. Vui lòng đọc nó vì giải quyết vấn đề này hoàn toàn và theo cách rất đúng.
laravel registry pattern
Câu hỏi hay. – simhumileco