龙空技术网

使用OpenWhisk对PHP进行依赖注入

爱码农 106

前言:

当前大家对“php依赖”大体比较关注,姐妹们都需要学习一些“php依赖”的相关知识。那么小编同时在网摘上搜集了一些有关“php依赖””的相关文章,希望同学们能喜欢,看官们一起来学习一下吧!

使用依赖注入容器是确保无服务器应用程序易于维护并且应用程序的功能得到适当分离的一种方法。

任何非平凡的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框架的应用程序中看到的控制器操作。

总结

即使在无服务器应用程序中,也需要一个干净的软件设计。所有的代码不属于动作的入口函数,应该适当分开。使用依赖注入容器是处理这种情况的一种方法,有助于确保无服务器应用程序可以轻松维护。

标签: #php依赖 #php依赖注入的三种方式