Yii2,组件,制作单个实例并在Web应用程序的任何位置访问它

时间:2017-12-09 21:01:52

标签: php yii2 yii2-basic-app

我想在yii2中创建一个可以在整个Web应用程序中访问的组件,但只创建一个实例并能够在任何需要的地方检索该实例。

namespace app\components;

use yii;
use yii\base\Object;

    class ContentManagerComponent extends Object
{
    public function init(){
        parent::init();
    }

    public function toBeUsed (){
        return 'some variable';
    }
}

然后我希望能够在Web应用程序的其他部分中调用该组件,就像在控制器中一样。

namespace app\Controllers;
use yii;
use app\controllers\

class SomeController extends Controller {

    public function actionDoSomething(){
    $contentComponent = Yii::$app->content;
    $someVariable = $contentComponent->toBeUsed()

    return $this->render( 'someView',[
        'variable' => $someVariable,
    ]

    }    

}

我还将组件放在web.php文件中。

$config = [
    'components' => [
        'content' => [
            'class' => 'app\components\ContentManagerComponent',
        ],
    ],
],

我最终得到的是phpstorm告诉我该课程不存在。我也想像应用程序中的其他组件一样拥有智能感知。

智能感知:

intelense

noIntele:

noIntele

更新:#

我可以通过添加以下答案建议的这一行来获得智能感知。 / ** @var ContentComponent $ contentManager * / 但是,每次我想使用内容组件时,我总是厌倦了输入。所以我在需要Content Component的组件的基类中创建了一个函数,它使用Yii :: app-> content方法返回Continent Component。在返回内容组件的函数上方,我添加了注释,它将返回ContentComponent和ContentComponent的类。现在为了让我使用具有智能感知功能的组件。我所要做的只是$ this-> getContentComponent。 Php storm将能够识别内容组件是返回的类。贝娄就是一个例子。

class BaseClass extends object
{

    /**
     * @return ContentComponent
    */
    function getContentComponent () {
        $contentComponent = Yii::app->content;
        return $contentComponent
    }
}

class SomeClass extends BaseClass

public function someFunction () {
    $contentComponent = $this->getContentComponent;
}

3 个答案:

答案 0 :(得分:2)

在配置文件中声明了content组件后

  $config = [
      'components' => [
          'content' => [
              'class' => 'app\components\ContentManagerComponent',
          ],
      ],
  ],

然后你可以使用

来引用组件
    Yii::$app->content

例如

    Yii::$app->content->yourMethod();

最终添加use Yii;或使用\Yii::$app->content

引用

答案 1 :(得分:2)

PHPStorm无法识别您的自定义组件,因为它们是在框架加载时动态创建的,并且在运行时附加到Yii::$app,这就是PHPStorm无法识别您的自定义组件的原因。因此,除非有人为PHPStorm等IDE开发智能插件,否则您必须进行一些调整才能实现目标。

您有两个选择:

  1. 创建一个新的Yii.php文件(在根目录中)以供所有参考 必要的文档,这将告诉PHPStorm整个项目 关于你的组件(我在这里提出了一个完整的例子,如果你想创建仅适用于控制台/ web /两者的组件),请查看* @property ContentManagerComponent $contentMore read - samdark Alexander Makarov,Yii之一核心贡献者):

    <?php
    
    use app\components\ContentManagerComponent;
    use yii\BaseYii;
    
    /**
     * Class Yii
     * Yii bootstrap file.
     * Used for enhanced IDE code autocompletion.
     */
    class Yii extends BaseYii
    {
        /**
         * @var BaseApplication|WebApplication|ConsoleApplication the application instance
         */
        public static $app;
    }
    
    /**
     * Class BaseApplication
     * Used for properties that are identical for both WebApplication and ConsoleApplication
     *
     * @property ContentManagerComponent $content
     */
    abstract class BaseApplication extends yii\base\Application
    {
    }
    
    /**
     * Class WebApplication
     * Include only Web application related components here
     *
     */
    class WebApplication extends yii\web\Application
    {
    }
    
    /**
     * Class ConsoleApplication
     * Include only Console application related components here
     */
    class ConsoleApplication extends yii\console\Application
    {
    }
    
  2. 在任何想要使用组件的地方创建一个PHP文档 将告诉PHPStorm您的变量是组件的实例:

    public function actionDoSomething()
    {
        /** @var ContentManagerComponent $contentComponent */
        $contentComponent = Yii::$app->content;
        $someVariable = $contentComponent->toBeUsed();
    
        return $this->render('someView', [
            'variable' => $someVariable,
        ]);
    }
    
  3. 正如您所看到的,选项1是由Yii框架的核心贡献者之一提供的解决方案,因此我假设这是现在正确的选择(直到JetBrains或任何插件将提供本机支持)

答案 2 :(得分:0)

我将以下方法用于智能感知。

1。在config中设置组件。

$config = [
    'components' => [
        'content' => [
            'class' => 'app\components\ContentManagerComponent',
        ],
        'content2' => [
            'class' => 'app\components\ContentManagerComponent2',
        ],
    ],
],

2。具有AppComponents特征,记录您的$app拥有的所有实例。我喜欢将其保存在components/目录中。

<?php

namespace app\components;

/**
 * Trait AppComponents
 * @package app\components
 *
 * @property ContentManagerComponent1 $content
 * @property ContentManagerComponent2 $content2
 */
trait AppComponents {}

3。以自己的方式返回Yii::$app。诱使编辑者相信可以返回AppComponents

<?php

namespace app\controllers;

use frontend\components\AppComponents;
use yii\rest\Controller;

class SiteController extends Controller {

    /**
     * @return \yii\web\Application|AppComponents
     */
    public static function app() {
        return \Yii::$app;
    }

}

现在,您可以将SiteController::app()->content与智能感知结合使用。您可以拥有一个更好的Root类,并将\Yii::$app替换为Root::app()。所有 Controllers 都可以继承Root类。在扩展的 Controllers 中进行编码时,也可以使用self::app()