从其他类访问Silex Application类;怎么注射?

时间:2015-09-21 07:42:56

标签: php silex

我目前正在开发我的第一个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模型的新实例。

有什么方法可以解决这个问题吗?

2 个答案:

答案 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']);