繁体   English   中英

使用Symfony 2.8,在自定义包/库中,我实际上如何使用加载的yml配置?

[英]With Symfony 2.8, in a custom bundle/library, how do I actually consume a loaded yml config?

我的经验仅限于Laravel,它使加载配置设置像\\Config::get('MySiteLibrary.customSetting');一样简单\\Config::get('MySiteLibrary.customSetting'); 并加载结构设置。

我现在正在编写一个Symfony兼容库,以与Drupal 8(基于Symfony 2.8构建)网站一起使用,以及与其他项目一起独立使用。

在此库中,我正在写我需要能够加载特定于环境的配置设置。 我发现了很多有关如何将所有内容放在Resources/config/config.yml and services.yml以及DependencyInjection\\Configuration.phpMyWhateverExtension.php 但是我发现的任何东西都没有向我展示如何在整个包/库中实际使用该配置。

有人可以证明这一点吗? 我已经厌倦了阅读Symfony过于复杂的文档,这些文档似乎并没有告诉您如何使用它。

更新:更具体地说,我正在创建一个API库,可以很容易地调用多个端点。 我想要构造它的方式是使调用的应用程序可以调用一个中心类,该中心类根据我在做什么来协调对端点的调用。

示例:应用程序需要创建一个新的客户帐户(必须调用3个不同的端点)。 因此它调用API::Customer::Account->create($data); 然后,create()方法按顺序调用端点。 这些端点在代码中是我创建的类,它们知道如何处理所述端点。 为了使这些端点更整洁,我正在注入一个Adapter类,该类了解与我们正在调用的整个API进行通信的细节(这些端点提供了特定于它们的详细信息)。

我要做的是在调用适配器时自动为适配器和端点实现依赖关系。 这意味着我配置了默认值,例如使用Guzzle作为配置文件中的主要客户端工具。 或者我使用x-logger记录所有内容。 DI容器会通知这些依赖项,并返回Adapter类的完全创建的实例。 我还希望能够从Adapter类以及其他地方轻松获取一些特定于环境的配置设置。 而且由于我要从20多个终结点类中访问它,所以我真的不想重复代码来一次又一次地注入配置。

所以是的,我确实知道Laravel降低了执行此操作的标准。 我不希望它以相同的方式工作。 我想做的就是找到一种以尽可能最小的方式加载该配置的方法。 我应该补充一点,我将使用的第一个地方是在Drupal 8项目中。

这是一个示例,代码如下所示:

<?php
namespace SomeCompany\API\Adapter;

use GuzzleHttp\ClientInterface;
use SomeCompany\API\Exception\ScException;
use Psr\Log\LoggerInterface;
use SomeCompany\API\Interfaces\ConfigInterface;

class SpecificAdapter extends BaseAdapter {
  public function __construct(LoggerInterface $logger, ClientInterface $client) {
    parent::__construct($logger, $client);

    $this->setDefaultSuccessStatus('0'); // From parent class
  }

  public function getAuth() {
    if ($this->shouldUsePrivateToken()) {
      return ConfigInterface::get('SomeCompany.api.auth_common');
    }

    if ($this->shouldUseAnonymousToken()) {
      return ConfigInterface::get('SomeCompany.api.auth_common');
    }

    if ($userToken = self::getUserToken()) {
      return "TOKEN: $userToken";
    }

    throw new ScException('Unable to find the appropriate token for this call.');
  }

  public static function getUserToken() {
    // This part is not ironed out yet. Don't judge me.
    return !empty($_SESSION['user_token']) ? $_SESSION['user_token'] : false;
  }

  public function shouldUseAnonymousToken() {
    // Some rules here the return a boolean
  }

  public function shouldUsePrivateToken() {
    // Some rules here the return a boolean
  }
}

然后,每个Endpoint类都使用它。

<?php
namespace SomeCompany\API\Endpoint\Customer;

use SomeCompany\API\Data\Account;
use SomeCompany\API\Endpoint\Endpoint;
use SomeCompany\API\Interfaces\AdapterInterface;
use SomeCompany\API\Exception\ScException;

class Accounts extends Endpoint {
  protected $processedResults = [];
  protected static $requiredFields = ['address1', 'city', 'state', 'zip', 'phone'];

  public function __construct(AdapterInterface $adapter) {
    parent::__construct($adapter);
    $this->getAdapter()->setUri('customer/accounts');
  }

  public function create($data) {
    if (empty($data) || (!is_array($data) && !is_object($data))) {
      throw new ScException('Unable to create a new account without data.');
    }

    $data = $this->filterParams($data, self::$requiredFields);
    $this->getAdapter()->setMethod('POST');
    $this->getAdapter()->setParams($data);

    $result = $this->getAdapter()->execute();

    if (isset($result->accountId)) {
      return $result->accountId;
    }

    return null;
  }

  protected function filterParams($data, array $required) {
    $data = (object) $data;
    $data->specialSetting = 'SpecialValue'; // Set the SpecialSetting default to "SpecialValue" for companies.

    //Verify required fields are set
    foreach ($required AS $field) {
      if (!isset($data->$field)) {
        throw new ScException("Missing required account field: $field");
      }

      if ($field == 'phone') {
        $data->phone = preg_replace('~.*(\d{3})[^\d]*(\d{3})[^\d]*(\d{4}).*~', '$1-$2-$3', $data->phone);
      }
    }

    if (empty($data->someMarker)) {
      $data->specialSetting  = 'NotSpecial'; // Forced to NotSpecial.
    }

    return (array) $data;
  }
}

端点本身是从编排如何使用它们的许多类中加载的。

也许我使如何做自己想做的事情过于复杂。 但是我非常想减少代码重复,我认为这对我正在做的事情来说是一个很大的问题。

根据这个 ,你可以检查环境,这样的:

$this->container->getParameter('kernel.environment'); 

根据这个 ,你可以检查parameters.yml参数装载机:

$container->getParameter('mailer.transport');

如果要加载这样的自定义配置文件:

use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Config\FileLocator;

// ...
public function load(array $configs, ContainerBuilder $container)
{
    $loader = new YamlFileLoader(
        $container,
        new FileLocator(__DIR__.'/../Resources/config')
    );
    $loader->load('services.xml');
}

您可以这样解析自定义的YAML文件:

use Symfony\Component\Yaml\Exception\ParseException;

try {
    $value = Yaml::parse(file_get_contents('/path/to/file.yml'));
} catch (ParseException $e) {
    printf("Unable to parse the YAML string: %s", $e->getMessage());
}

// var $value is an associative array

希望这可以帮助 !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM