[英]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.php
和MyWhateverExtension.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.