任何非平凡的PHP运用程序都利用各种组件来完成他们的事情,从PDO到Packagist的类。在标准的PHP运用程序中,利用依赖注入来配置和加载这些类是很常见的。我们如何在无做事器的环境(如OpenWhisk)中实行此操作?
涌现这个问题是由于我们没有一个入口点进入我们的运用程序,相反,我们每个操作都有一个入口点。如果我们利用无做事器来编写API,那么我们可能会在同一个项目中有一组读取,创建,更新和删除资源的操作。
考虑一个利用PDO与数据库通信的项目。PDO工具须要利用包含主机名,数据库,凭据等的DSN字符串实例化。它们可能会存储在通报给操作的参数数组中,并将其设置为包参数或做事绑定您正在利用IBM Cloud Functions。

在这个例子中,我在IBM的OpenWhisk做事中设置了一个ElephantSQL数据库,并且我利用了Lorna Mitchell 对OpenWhisk Packages相称有用的Bind Services项目,以使证书可用于我的OpenWhisk操作。
在动作中利用PDO实例考虑这个操作,它返回数据库中的待办事项清单。首先,我们实例化和配置PDO实例,然后创建一个可以获取待办事项的映射器工具:
function main(array $args) : array
{
if (!isset($args['__bx_creds']['elephantsql']['uri'])) {
throw new Exception(\"大众ElephantSQL instance has not been bound\"大众);
}
$credentials = parse_url($args['__bx_creds']['elephantsql']['uri']);
$host = $credentials['host'];
$port = $credentials['port'];
$dbName = trim($credentials['path'], '/');
$user = $credentials['user'];
$password = $credentials['pass'];
$dsn = \"大众pgsql:host=$host;port=$port;dbname=$dbName;user=$user;password=$password\公众;
$pdo = new PDO($dsn);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// now we can use $pdo to interact with our PostgreSQL database via a mapper
$mapper = new TodoMapper($pdo);
$todos = $mapper->fetchAll();
return [
'statusCode' => 200,
'body' => $todos,
];
}
这是相称多的设置代码,显然不属于这里,特殊是由于我们须要在连接到数据库的项目的每个操作中实行相同的操作。我们也可能会将我们的数据库访问代码放在一个将PDO实例作为依赖关系的映射器类中,因此,在我看来,在我们的项目中利用DI容器是故意义的。
我选择利用Pimple DI容器, 由于它很好,大略而且快速。
为了利用它,我扩展了Pimple \ Container并将我的工厂添加到布局函数中:
<?php
namespace App;
use InvalidArgumentException;
use PDO;
use Pimple\Container;
class AppContainer extends Container
{
public function __construct(array $args)
{
if (!isset($args['__bx_creds']['elephantsql']['uri'])) {
throw new InvalidArgumentException(\"大众ElephantSQL instance has not been bound\"大众);
}
$credentials = parse_url($args['__bx_creds']['elephantsql']['uri']);
/ Factory to create a PDO instance /
$configuration[PDO::class] = function (Container $c) use ($credentials) {
$host = $credentials['host'];
$port = $credentials['port'];
$dbName = trim($credentials['path'], '/');
$user = $credentials['user'];
$password = $credentials['pass'];
$dsn = \"大众pgsql:host=$host;port=$port;dbname=$dbName;user=$user;password=$password\公众;
$pdo = new PDO($dsn);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
};
/ Factory to create a TodoMapper instance /
$configuration[TodoMapper::class] = function (Container $c) : TodoMapper {
return new TodoMapper($c[PDO::class]);
};
parent::__construct($configuration);
}
}
在这段代码中,我们创建了两个工厂:一个创建PDO实例,另一个创建一个名为的映射器类 TodoMapper。该TodoMapper 班通过它的布局组成一个PDO实例,因此在工厂中TodoMapper,我们检索容器中的PDO实例。
这样做的好处是,如果一个动作不该用a TodoMapper,那么与数据库的连接就不会被完成,由于它不须要。
在行动中利用DIC现在我们的行为中的代码变得更清洁,更随意马虎阅读:
function main(array $args) : array
{
$container = new App\AppContainer($args);
$mapper = $container[App\TodoMapper::class];
$todos = $mapper->fetchAll();
return [
'statusCode' => 200,
'body' => $todos,
];
}
事实上,它现在看起来更像是一个在标准的基于PHP框架的运用程序中看到的掌握器操作。
总结纵然在无做事器运用程序中,也须要一个干净的软件设计。所有的代码不属于动作的入口函数,该当适当分开。利用依赖注入容器是处理这种情形的一种方法,有助于确保无做事器运用程序可以轻松掩护。