我有很多配置设置,我希望能够在整个应用程序中访问这些设置。例如,我有一个包含一些自定义查询的实体存储库。我想要一个全局参数,将默认“限制”设置为 10 条记录,除非我专门更改它。
class ViewVersionRepository extends EntityRepository {
/**
* Get all the versions for the specified view id, ordered by modification time.
* @param integer $id
* @param integer $limit
* @param integer $offset default 0
* @return array
*/
public function findByViewIdLimit($id, $limit = NULL, $offset = 0) {
// this won't work because we don't have access to the container... ;(
$limit = ($limit != NULL) ? $limit : $this->container->getParameter('cms.limit');
return $this->createQueryBuilder('v')
->where('v.viewId = :id')
->orderBy('v.timeMod', 'DESC')
->setParameter('id', $id)
->setFirstResult($offset)
->setMaxResults($limit)
->getQuery()
->getResult();
}
}
在我使用 Symfony 之前的生活中,我可以很容易地在我的 parameters.yml 中设置它:
cms.limit: 10
或者在一些应用程序配置文件中为此创建一个常量:
define('cms.limit', 10);
但是在 Symfony 中,如果我使用一个参数,我该如何从我的实体存储库访问它,因为“容器”在实体存储库中不可用?
人们说“将其作为参数传递”,但老实说,每次我调用查询时,这都是一种困惑和无意义的工作。如果您无法访问它们,那么拥有参数有什么意义!
其他人说你必须构建一些 global service model (我也还没有理解,似乎只是为了获取参数而付出了巨大的努力)。
那么在任何上下文(包括此处的上下文)中访问此类全局参数的“最佳”方法是什么?
我不想访问内核,但如果那是最后的手段,为什么从内核获取参数是“错误的”:
global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');
我不敢相信访问全局参数这么难。我理解需要明确说明依赖关系的想法。但是在参数始终可用的应用程序中,并且您总是希望将它们用作默认值,为什么这不是标准且简单的呢?
根据下面的回答,我已经将我的 ViewVersionRepository 变成了一项服务(这就是您的建议,对吗?)。
class ViewVersionRepository extends EntityRepository
{
// do not evidently need to set $this->viewVersion either
// protected $viewVersion;
protected $limit;
/**
* Allow limit to be set by parameter, injected by service definition
* @param $limit
*/
public function setLimit($limit) {
$this->limit = $limit;
}
/**
* Get all the versions for the specified view id, ordered by modification time.
* @param integer $id
* @param integer $limit default from global parameter
* @param integer $offset default 0
* @return array
*/
public function findByViewIdLimit($id, $limit = NULL, $offset = 0) {
$limit = (!empty($limit)) ? $limit : $this->limit;
return $this->createQueryBuilder('v')
->where('v.viewId = :id')
->orderBy('v.timeMod', 'DESC')
->setParameter('id', $id)
->setFirstResult($offset)
->setMaxResults($limit)
->getQuery()
->getResult();
}
}
添加服务:
gutensite_cms.view_version_repository:
class: Gutensite\CmsBundle\Entity\View\ViewVersionRepository
factory_service: 'doctrine.orm.default_entity_manager'
factory_method: 'getRepository'
arguments:
- 'Gutensite\CmsBundle\Entity\View\ViewVersion'
calls:
- [setLimit, ['%cms.limit.list.admin%']]
这会导致提示 factory_service 定义的错误:
You have requested a non-existent service "doctrine.orm.default_entity_manager". Did you mean one of these: "doctrine.orm.cms_entity_manager", "doctrine.orm.billing_entity_manager"?
幸运的是,如果我将 factory_service 更改为建议的 doctrine.orm.cms_entity_manager 它会起作用。 谁能解释为什么?
但随后我收到另一个与存储库中不存在的方法相关的错误(因为存储库已损坏)。我认为在服务定义中包含参数,意味着我需要向 ViewVersionRepository 添加一个 __construct($viewVersion) 方法来接受参数列表。但这导致了破坏存储库的严重错误。所以我删除了它,因为显然这必须在默认的 Symfony EntityRepository 中(我怎么知道的?)。我确实保留了一个自定义的 setLimit() 方法,用于将全局参数传递到调用中。
所以现在服务可以工作了……但这似乎是一大堆工作,只是为了访问全局参数,如果没有参数传递到方法中,这些参数应该作为默认值运行。
为什么我们不应该在这些设置默认值的情况下使用 $GLOBAL 或配置文件中的常量?这不会破坏依赖模型,自定义变量可以仍然被传递到方法中,只有我们有一个全局应用程序范围的默认值。我不明白为什么有人不赞成...
最佳答案
值得研究和了解如何将存储库创建为服务。像这样的东西:
view_version_repository:
class: My\SomeBundle\Entity\ViewVersionRepository
factory_service: 'doctrine.orm.default_entity_manager'
factory_method: 'getRepository'
arguments:
- 'My\SomeBundle\Entity\ViewVersion'
calls:
- [setLimit, ['%limit_parameter%']]
在你的 Controller 中你会做:
$viewVersionRepository = $this->container->get('view_version_repository');
参见文档:http://symfony.com/doc/current/components/dependency_injection/factories.html
在学习如何使用服务方面所付出的努力将获得数倍的返回。
关于php - 在实体库或任何地方访问 Symfony 配置参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23701852/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我有一个在Linux服务器上运行的ruby脚本。它不使用rails或任何东西。它基本上是一个命令行ruby脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm