Yii2,Component,创建一个实例并在Web应用程序中随处访问它

Yii2, Component, Make a single instance and access it everywhere in the web application

我想在 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 告诉我 class 不存在。我也希望像应用程序中的其他组件一样拥有智能感知。

智能感知:

无智能:

更新:#

我能够按照以下答案的建议添加这一行来让智能感知工作。 /** @var ContentComponent $contentManager */ 然而,每次我想使用内容组件时,我都厌倦了总是在上面输入这些内容。因此,我在需要内容组件的组件的基础 class 中创建了一个函数,该组件使用 Yii::app->content 方法 return 大陆组件。在 return 内容组件的函数上方,我添加了注释,它会 return ContentComponent 和 class 的 ContentComponent。现在为了让我使用具有智能感知功能的组件。我所要做的就是 $this->getContentComponent。 Php 风暴将能够识别内容组件属于 class returned。贝娄就是一个例子。

class BaseClass extends object
{

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

class SomeClass extends BaseClass

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

一旦您在配置文件中声明了 content 组件

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

然后您可以使用

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

例如

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

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

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

您有 2 个选择:

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

    <?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,
        ]);
    }
    

如您所见,选项 1 是由 Yii 框架的核心贡献者之一提供的解决方案,所以我认为这应该是目前的正确选择(直到 JetBrains 或任何其他公司提供原生支持)插件)

我使用以下方法进行智能感知。

1.Set 配置中的组件。

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

2.Have 一个 AppComponents 特质 ,记录你的 $app 拥有的所有实例。我喜欢把它放在 components/ 目录中。

<?php

namespace app\components;

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

3.ReturnYii::$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 class,并用 Root::app() 替换 \Yii::$app。所有 控制器 都可以继承自 Root class。在扩展 Controllers.

中编码时,您也可以使用 self::app()