简体   繁体   English

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

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

My experience has been limited to Laravel, which makes loading config settings as simple as \\Config::get('MySiteLibrary.customSetting'); 我的经验仅限于Laravel,它使加载配置设置像\\Config::get('MySiteLibrary.customSetting');一样简单\\Config::get('MySiteLibrary.customSetting'); and it loads the structure setting. 并加载结构设置。

I am now in the process of writing a Symfony compatible library to use with a Drupal 8 (which is built on Symfony 2.8) website as well as standalone usage with other projects. 我现在正在编写一个Symfony兼容库,以与Drupal 8(基于Symfony 2.8构建)网站一起使用,以及与其他项目一起独立使用。

In this library I am writing I need to be able to load environment specific config settings. 在此库中,我正在写我需要能够加载特定于环境的配置设置。 I have found tons of stuff on how to put everything under Resources/config/config.yml and services.yml as well as the DependencyInjection\\Configuration.php and MyWhateverExtension.php . 我发现了很多有关如何将所有内容放在Resources/config/config.yml and services.yml以及DependencyInjection\\Configuration.phpMyWhateverExtension.php But nothing I have found shows me how to actually use that config throughout your bundle/library. 但是我发现的任何东西都没有向我展示如何在整个包/库中实际使用该配置。

Can someone please demonstrate this? 有人可以证明这一点吗? I am getting tired of reading through the overcomplicated docs for Symfony that do not seem to actually tell you how to use it once it is all wired up. 我已经厌倦了阅读Symfony过于复杂的文档,这些文档似乎并没有告诉您如何使用它。

UPDATE: To be more specific I am creating an API library that can call multiple endpoints pretty easily. 更新:更具体地说,我正在创建一个API库,可以很容易地调用多个端点。 The way I want to structure it is so that the calling app can call a central class that orchestrates calls to the endpoints based on what I am doing. 我想要构造它的方式是使调用的应用程序可以调用一个中心类,该中心类根据我在做什么来协调对端点的调用。

Example: The app needs to create a new customer account (to which 3 different endpoints have to be called). 示例:应用程序需要创建一个新的客户帐户(必须调用3个不同的端点)。 So it calls API::Customer::Account->create($data); 因此它调用API::Customer::Account->create($data); . The create() method then calls the endpoints in order. 然后,create()方法按顺序调用端点。 These endpoints, in code, are classes I created that know how to deal with said endpoint. 这些端点在代码中是我创建的类,它们知道如何处理所述端点。 To make those endpoints cleaner I am injecting an Adapter class that knows about the details of communicating with the overall API we are calling (the endpoints provide details that a specific to them). 为了使这些端点更整洁,我正在注入一个Adapter类,该类了解与我们正在调用的整个API进行通信的细节(这些端点提供了特定于它们的详细信息)。

What I want to do is have the dependencies automatically fulfilled for the adapter and for the endpoints when I call them. 我要做的是在调用适配器时自动为适配器和端点实现依赖关系。 This means that I configure defaults such as using Guzzle as the primary client tool from a config file. 这意味着我配置了默认值,例如使用Guzzle作为配置文件中的主要客户端工具。 Or that I use x-logger to log everything. 或者我使用x-logger记录所有内容。 The DI container news up those dependencies and returns a fully created instance of the Adapter class. DI容器会通知这些依赖项,并返回Adapter类的完全创建的实例。 I want to also be able to easily grab some environment-specific config settings from within the Adapter class and possibly elsewhere. 我还希望能够从Adapter类以及其他地方轻松获取一些特定于环境的配置设置。 And since I am accessing this from 20+ endpoint classes I really don't want to repeat code to inject the configuration in over and over again. 而且由于我要从20多个终结点类中访问它,所以我真的不想重复代码来一次又一次地注入配置。

So yes, I do know that Laravel lowers the bar for doing this. 所以是的,我确实知道Laravel降低了执行此操作的标准。 I don't expect it to work the same way. 我不希望它以相同的方式工作。 What I want to do though is to find a way to load that config in the most minimalist way possible. 我想做的就是找到一种以尽可能最小的方式加载该配置的方法。 I should add that the first place I will be using this is in a Drupal 8 project. 我应该补充一点,我将使用的第一个地方是在Drupal 8项目中。

This is an example what the code looks like: 这是一个示例,代码如下所示:

<?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
  }
}

This is then used by each of the Endpoint classes... 然后,每个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;
  }
}

The endpoints themselves are loaded from a number of classes that orchestrate how they are used. 端点本身是从编排如何使用它们的许多类中加载的。

Maybe I am overcomplicating how to do what I want to do. 也许我使如何做自己想做的事情过于复杂。 But I greatly want to reduce code duplication and I see this as being a pretty big issue with what I am doing. 但是我非常想减少代码重复,我认为这对我正在做的事情来说是一个很大的问题。

According to this , you can check the environment, like that : 根据这个 ,你可以检查环境,这样的:

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

According to this , you can check a parameter loader in parameters.yml : 根据这个 ,你可以检查parameters.yml参数装载机:

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

If you want to load an custom configuration file like this : 如果要加载这样的自定义配置文件:

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');
}

You can parse the custom YAML file like this : 您可以这样解析自定义的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

Hope this helps ! 希望这可以帮助 !

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

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