我尝试从数据库加载参数,而不是对parameters.yml
中的参数进行硬编码。并不是parameters.yml中的所有参数都需要从数据库中加载,只有几个,比如贝宝的api详细信息
在config.yml
中,我导入了parameters.php
imports:
- { resource: parameters.php }
如果我像下面这样在parameters.php
中添加静态信息,它可以很好地进行
$demoName = 'First Last';
$container->setParameter('demoName', $demoName);
但是,我无法从数据库表中获取信息。我想我应该创建类并使用$em = this->getDoctrine()->getManager();
,它应该可以工作,但它没有,我得到了的错误
Notice: Undefined variable: paypal_data in /opt/lampp/htdocs/services/app/config/parameters.php (which is being imported from "/opt/lampp/htdocs/services/app/config/config.yml").
这是我的尝试,如下所示,但代码似乎没有进入__construct()
use Symfony'Bundle'FrameworkBundle'Controller'Controller;
use Doctrine'Bundle'DoctrineBundle'Registry;
use Doctrine'ORM'Mapping as ORM;
class parameters extends Controller
{
public $paypal_data;
function __construct() {
$this->indexAction();
}
public function indexAction(){
$em = $this->getDoctrine()->getManager();
$this->paypal_data = $em->getRepository('featureBundle:paymentGateways')->findAll();
}
}
$demoName = 'First Last';
$container->setParameter('demoName', $demoName);
$container->setParameter('paypal_data', $this->paypal_data);
任何帮助都将不胜感激。
你做的事情不对。您需要声明CompilerPass并将其添加到容器中。整个集装箱将被装载后。。。在编译时,您将可以访问其中的所有服务。
只需获取实体管理器服务并查询所需的参数,然后将它们注册到容器中。
分步指令:
-
定义编译器过程:
# src/Acme/YourBundle/DependencyInjection/Compiler/ParametersCompilerPass.php class ParametersCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $em = $container->get('doctrine.orm.default_entity_manager'); $paypal_params = $em->getRepository('featureBundle:paymentGateways')->findAll(); $container->setParameter('paypal_data', $paypal_params); } }
-
在bundle定义类中,您需要将编译器传递添加到容器中
# src/Acme/YourBundle/AcmeYourBundle.php class AcmeYourBundle extends Bundle { public function build(ContainerBuilder $container) { parent::build($container); $container->addCompilerPass(new ParametersCompilerPass(), PassConfig::TYPE_AFTER_REMOVING); } }
在我的Symfony 4中,带有CompilerPass
的解决方案不起作用,它只从控制器起作用,但在twig.yaml文件中使用时不起作用:
param_name: '%param_name%'
因为我需要在侧边栏中使用这个参数,所以在所有页面中,从控制器传递它是不可行的。
这就是我所做的,因为你可以将服务引用为全局Twig变量。
我有一个名为"设置"的服务,它直接从数据库加载设置,简化为:
class Settings
{
private Connection $db;
public function __construct(EntityManagerInterface $em)
{
$this->db = $this->em->getConnection();
}
/**
* Get a setting value.
* If the setting doesn't exist, return the default value specified as the second param
*/
public function get(string $name, $default=''): string
{
$val = $this->db->executeQuery("SELECT `value` FROM `settings` WHERE `key`=?;", [$name])->fetchOne();
// strict comparison is needed for cases when $val === '0'
return $val !== false ? $val : $default;
}
/**
* Set a setting value.
* If the setting doesn't exist, create it. Otherwise, replace the db value
*/
public function set(string $name, ?string $value, string $description = '')
{
if(is_null($value)) {
// Remove the key
$this->db->executeQuery('DELETE FROM settings WHERE `key`=?;', [$name]);
return;
}
$this->db->executeQuery('INSERT INTO settings (`key`, `type`, `value`, `description`) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE `type`=?, `value`=?, `description`=?;',
[$name, $type, $value, $description, $type, $value, $description]);
}
现在,我简单地添加了config/packages/twig.yaml
:
twig:
# ...
globals:
# ...
settings: '@App'Service'Settings'
这太神奇了,因为现在我可以从任何模板中读取任何数据库设置:
{{ dump(settings.get('setting_name')) }}
我发布的Settings类被简化了,它仍然可以改进,例如,如果您多次请求相同的设置,则可以避免再次进行相同的查询,但这很简单(将提取的密钥存储在private $fetched
数组中),或者使用warmup(array $keys)
方法通过单个查询("SELECT key, value FROM settings WHERE key IN (?);", [$toFetch], [Connection::PARAM_STR_ARRAY]
)提取多个设置