我目前正在开发我的第一个Silex(2.0)项目。我定义了一些Pheasant模型,我可以从我的控制器中访问:
edges = [
{
"source": "A",
"target": "B",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "A",
"target": "C",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "B",
"target": "C",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "D",
"target": "C",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "C",
"target": "E",
"other information" : "randomstring",
"other information" : "randomstring"
}
]
var res = edges.reduce(function (acc, cur, i, array) {
if (array[i - 1] == undefined || acc[acc.length - 1].target == cur.source) {
acc.push(cur)
}
return acc
}, [])
console.log(res)
现在,在某些情况下,我想在我的模型中访问Application类。例如,检查我们是否在调试模式下运行(或不运行)。现在:
// it is used both static
$p = \Model\Post::oneById(3);
// .. and with an instance
$p = new \Model\Post;
$p->title = 'foobar';
$p->save();
但这并不像Silex。所以我想我需要某种能自动将public function beforeSave() {
global $app;
if($app['debug']) {
// ...
}
}
类注入我的模型的东西:
$app
这适用于某个级别,但在调用class PheasantModelReflector {
protected $app;
public function __construct(\Silex\Application $app) {
$this->app = $app;
}
public function __get($className) {
$r = (new ReflectionClass(sprintf('Model\%s', $className)))->newInstance();
$r->__invoke($this->app);
return $r;
}
}
$app['model'] = function ($app) {
return new PheasantModelReflector($app);
};
时始终返回Post模型的新实例。
有什么方法可以解决这个问题吗?
答案 0 :(得分:1)
如果没有使用Pheasant,我可能会尝试创建一个服务工厂,将$ app(或$ debug var)注入到您的实体类中(这里的一个问题是您的实体必须扩展\Pheasant\DomainObject
并且您不能将构造函数覆盖为issue):
<?php
// in the example below I inject the whole $app, if you only need the
// debug var, inject only that, injecting the whole $app may
// tempt you to use it as a service locator
// creating a new instance
$app['model_post_factory'] = $app->factory(function ($app) {
$post = new \Model\Post();
$post->setApp($app);
return $post;
});
$post = $app['model_post_factory'];
// getting an instance by ID, here it gets a little tricky
$app['model_post_static_factory'] = function($app, $id) {
$post = \Model\Post::oneById($id);
$post->setApp($app);
return $post;
}
$postById = $app->raw('model_post_static_factory');
$post = $postById($app, $id); // $id comes from somewhere else
// depending on the PHP version you may try directly:
// $post = $app->raw('model_post_static_factory')($app, $id);
静态方法的问题是传递id参数。您可以使用 use 关键字从外部作用域导入$ id的工厂范围,但恕我直言这太神奇了(虽然我也不太喜欢替代)。可能会有更优雅的方式,但我现在想不到。
答案 1 :(得分:0)
每次需要创建共享服务(http://silex.sensiolabs.org/doc/services.html)时,要避免生成新的模型实例。 例如:
$app['model'] = $app->share(function () {
return new PheasantModelReflector();
});
无论如何注入$app
不一定是个好主意,也许你可以只注入每个对象的依赖?类似的东西:
new \Model\Post($app['debug']);