我正在使用Slim和php-di作为容器,我一直在试图弄清楚如何autowire依赖项没有成功。
我想将App\Models\Planner.php
注入App\Controllers\MealPlanner.php
中,以及由不同端点/方法/动作调用的其他各种类和模型。
现在在Services.php上,我正在创建4个服务2,这些服务将传递给其他类,以及2个工厂,分别是Planner.php和MealPlanner.php,在路由器中被调用在index.php上。
现在将MealPlanner定义为服务,可以直接从$app->any('/mealplanner/{action}', \MealPlanner::class);
调用它,如果删除$app->set('MealPlanner', ...)
,我将得到“ Callable MealPlanner不存在”,为什么可调用在那里没有进入容器?
第二,假设我想将Fruits类与Planner.php一起注入MealPlanner,为此,我必须添加一个新服务$container->set("Fruits", (){ return App\Models\Fruits.php(PDO $db, $UserId) })
,然后在MealPlanner服务上将水果容器传递到那里,然后在MealPlanner控制器上将其变为:
public function __construct(App\Models\Planner $planner, App\Models\Fruits $fruits)
就个人而言,必须将它们传递通过服务容器,然后必须在控制器上进行更改,这很烦人,在这里我可能会误解。
假设我决定将上面的代码删除,取而代之的是"slim will instantiate the container",MealPlanner.php现在应该是
namespace App\Controllers;
use Psr\Container\ContainerInterface;
class MealPlanner extends InvokeAction {
public function __construct(ContainerInterface $container){
$this->container = $container;
}
public function init($request, $response, $args){
// return something
}
}
我必须从容器中删除MealPlanner工厂,所以路由类定义将停止工作,并且我必须使用它的绝对路径来工作$app->any('/mealplanner/{action}', \App\Controllers\Planner::class);
,现在所有服务都喜欢可通过容器访问“数据库”和“计划器”,但是我仍然必须创建服务(例如Fruits),因此无法掌握自动装配的工作方式,因为它们在类型提示时未定义绝对路径。 / p>
答案 0 :(得分:1)
我创建了一个将Slim 4和Eloquent ORM结合在一起的框架,称为Willow。这是我使用PHP-DI的方法:
<?php
declare(strict_types=1);
namespace Willow\Main;
use DI\ContainerBuilder;
use Slim\Factory\AppFactory;
class App
{
public function __construct()
{
// Set up Dependency Injection
$builder = new ContainerBuilder();
// Read in each config file to inject. See db.php below as an example
foreach (glob(__DIR__ . '/../../config/*.php') as $definitions) {
$builder->addDefinitions(realpath($definitions));
}
$container = $builder->build();
// Get an instance of Slim\App and inject the container.
AppFactory::setContainer($container);
$app = AppFactory::create();
}
}
<?php
declare(strict_types=1);
use Illuminate\Database\Capsule\Manager as Capsule;
use Psr\Container\ContainerInterface;
// By returning this array it sets up Capsule::class to be injected via DI
return [
Capsule::class => function (ContainerInterface $c) {
$eloquent = new Capsule;
$eloquent->addConnection([
'driver' => env('DB_DRIVER') ?? 'mysql',
'host' => getenv('DB_HOST'),
'port' => getenv('DB_PORT') ?? '',
'database' => getenv('DB_NAME'),
'username' => getenv('DB_USER'),
'password' => getenv('DB_PASSWORD'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => ''
]);
// Make this Capsule instance available globally via static methods
$eloquent->setAsGlobal();
// Setup the Eloquent ORM...
$eloquent->bootEloquent();
// Set the fetch mode to return associative arrays.
$eloquent->setFetchMode(PDO::FETCH_ASSOC);
return $eloquent;
}
];