我想一般回答这个问题,但为了说明一下,这是一个用例:
我正在使用Vagrant进行简单的LMAP项目.我使用独立的Puppet进行配置.现在,可能有一些开发人员坐在代理后面,他们需要对VM进行一些额外的配置.我有事情在Puppet方面工作:我可以将代理IP(如果有的话)作为事实传递给Ppetpet中的Vagrantfile木偶,如果它已经设置,Puppet会做出相应的反应.
我唯一的问题是:开发人员如何为他们的开发环境指定/覆盖此设置而无需更改Vagrantfile(在版本控制下并且必须保持dev-environment-neutral)?
如果人们可以覆盖一个名为例如Vagrantfile.local我将排除通过的文件中的一些Vagrant设置,那将是非常棒的.gitignore.
由于Vagrantfile只是Ruby,我尝试了以下内容:
# Also load per-dev custom vagrant config
custom_vagrantfile = 'Vagrantfile.local'
load custom_vagrantfile if File.exist?(custom_vagrantfile)
Run Code Online (Sandbox Code Playgroud)
文件包含基本上是可行的,但它看起来像在包含的文件中,我不再在同一个Vagrant上下文中...
Vagrant::Config.run do |config|
config.vm.provision :puppet do |puppet|
puppet.facter = { "proxy" => "proxy.host:80" }
end
end
Run Code Online (Sandbox Code Playgroud)
...还"重置"我在主要部分制作的所有其他木偶配置值Vagrantfile,这让我觉得我在这里朝着错误的方向前进.我应该注意到我在Ruby的总菜鸟;)
任何人都可以给我一个提示,甚至是一个有效的解决方案,可以在这里完成per-dev定制吗?
首先,我没有使用FOSUserBundle,我不能,因为我正在移植一个遗留系统,它有自己的模型层(没有Doctrine/Mongo /无论在这里)和其他非常自定义的行为.
我正在尝试将我的遗留角色系统与Symfony连接,因此我可以在控制器和视图中使用本机symfony安全性.
我的第一次尝试加载并返回该用户的所有角色在getRoles()从方法Symfony\Component\Security\Core\User\UserInterface.起初,它看起来像是有效的.但在深入了解之后,我注意到这些角色只有在用户登录时才会刷新.这意味着如果我从用户授予或撤消角色,他将必须注销并重新登录才能使更改生效.但是,如果我从用户撤消安全角色,我希望立即应用该角色,这样我就无法接受这种行为.
我希望Symfony做的是在每个请求上重新加载用户的角色,以确保它们是最新的.我已经实现了一个自定义用户提供程序,并且refreshUser(UserInterface $user)每次请求都会调用其方法,但不会以某种方式刷新角色.
在我的UserProvider中加载/刷新用户的代码如下所示:
public function loadUserByUsername($username) {
$user = UserModel::loadByUsername($username); // Loads a fresh user object including roles!
if (!$user) {
throw new UsernameNotFoundException("User not found");
}
return $user;
}
Run Code Online (Sandbox Code Playgroud)
(refreshUser看起来很相似)
有没有办法让Symfony在每个请求上刷新用户角色?
当我们现在开始在几个项目中使用Symfony 2时,我们发现在我们的项目中可以分享相当多的代码.因此,我们开始将功能提取到Symfony 2包中,以便在我们的项目之间共享它们.
虽然我们基本上已经开始工作了,但仍然有很多问题不容易进行,但特别是在测试共享捆绑时.
我们提取的第一个小包包含一个Doctrine Entity,一个kernel.event_listener被自动注入客户端项目的DI容器,一个注释,另一个服务和几个命令.基本思想是客户端项目可以使用我们的注释来注释其控制器,event_listener将拦截对注释控制器的请求,并在最终调用控制器之前执行一些额外的逻辑(涉及教义实体).这些命令用于管理doctrine实体的数据库条目.
到目前为止,一切都完全符合我们的预期,但我们正在努力解决捆绑的可测性问题.首先,保存包的Git存储库不包含完整的Symfony2项目.这样做有点矫枉过正,因为我们只在这里构建一个捆绑包,而不是整个应用程序,对吧?
但是我们如何测试事件监听器呢?我们如何测试它被注入DI容器?我们需要一个测试控制器,它将使用我们的特殊注释进行注释,因此我们可以测试我们的事件监听器是否正确捕获它.该控制器必须在测试时才可用,并且绝不能出现在任何客户端应用程序中.
我们如何测试命令?我们需要模仿学说背后的数据库.当我们尝试在一个简单引导的phpunit测试中执行命令时/vendor/autoload.php,当然我们得到:
致命错误:在第3行的/.../vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php中调用未定义的方法Symfony\Component\Console\Application :: getKernel()
所以感觉就像我们最终需要在我们的bundle的存储库中需要一个完整的Symfony2项目才能引导整个框架以最终测试我们的组件.当我查看开源Symfony2软件包时,我发现没有将整个框架检入他们的Git存储库,所以这仍然感觉不对.
我错过了什么?是否有关于Bundle-Only/Applicationless捆绑开发的文档我缺少?
我在这里找到了一个命令测试解决方案:http://www.ricardclau.com/2013/02/testing-symfony2-commands-mocking-the-di-container-with-mockery/
事实证明,错误来自于ContainerAwareCommand尝试创建一个新容器,这显然不适用于裸测试环境.我通过模拟容器并手动将其注入Command中解决了这个问题,如下所示:
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class MyCommandTest extends \PHPUnit_Framework_TestCase {
public function testExecute() {
$application = new Application();
$application->add(new MyCommand());
$command = $application->find('my:command');
$command->setContainer($this->getMockContainer()); // <= This avoids ContainerAwareCommand creating a 'real' container in a test env
$commandTester = new CommandTester($command);
$commandTester->execute(array('command' => $command->getName()));
print $commandTester->getDisplay();
$this->assertRegExp('/.../', $commandTester->getDisplay());
}
protected function getMockContainer() {
// Mock …Run Code Online (Sandbox Code Playgroud) symfony ×2
bundle ×1
composer-php ×1
git ×1
phpunit ×1
roles ×1
ruby ×1
security ×1
symfony-2.1 ×1
vagrant ×1