【问题标题】:model exist or not in YII using a custom function - Performance使用自定义函数在 YII 中是否存在模型 - 性能
【发布时间】:2013-11-22 10:27:33
【问题描述】:

我正在编写一个 REST API,需要检查目录中是否存在给定模型名称的天气。

1 - http://example.com/RestApi/index.php/api/posts/

2 - http://example.com/RestApi/index.php/api/post/

从这两个中,URL 1 不正确,URL 2 正确(post)。所以我正在使用这个参数并进行如下搜索,

  $model = $m::model()->findAll($criteria);
  $m = TK::get('model');

当 $m 不正确时,PHP 警告 include(posts.php): failed to open stream: No such file or directory will tr​​igger.

为了避免这种情况发生,我编写了一个函数作为 modelExists() 并像下面这样使用它。

If (!TK::modelExists($m))
            $this->sendResponse(false, 1003);

函数体如下,

/**
     * Checks for a given model name
     * @param string $modelName is the name of the model that is used to search against the directory.
     * @return String $result, the name of Model. if doesnt exist NULL;
     */
    public static function modelExists($modelName)
    {
        $result = null;
        $basePath = Yii::getPathOfAlias('application').DIRECTORY_SEPARATOR;
        $modelsDir = 'models'.DIRECTORY_SEPARATOR;
        $modelName = strtolower($modelName).'.php';
        $generalModelDir = scandir($basePath.$modelsDir);

        foreach ($generalModelDir as $entry) { // Searching in General model directory
            if ($modelName == strtolower($entry)) {
                $temp = explode('.', $entry); // array('User','php')
                $result = $temp[0];
                break;
            }
        }

        if (!$result) {
            $modulePath = $basePath.'modules'.DIRECTORY_SEPARATOR;
            $moduleDirectory = scandir($modulePath);
            foreach ($moduleDirectory as $dir) {
                $subModuleDirectory = scandir($modulePath.$dir);
                foreach ($subModuleDirectory as $entry) {
                    if (is_dir($modulePath.$dir.DIRECTORY_SEPARATOR.$entry)) {
                        $directories = scandir($modulePath.$dir.DIRECTORY_SEPARATOR.$entry);
                        foreach ($directories as $subDir) {
                            if ($modelName == strtolower($subDir)) {
                                $temp = explode('.', $subDir); // array('User','php')
                                $result = $temp[0];
                                break;
                            }
                        }
                    }
                }
            }
        }
        return $result;
    }

我的问题是:这会导致任何性能问题,因为我正在检查每个 API 调用吗?

【问题讨论】:

    标签: php web-services api rest yii


    【解决方案1】:

    为什么不只是拥有项目中所有类的地图。这样您就可以使用它而不是一直查看磁盘。

    看看composer。是的,我知道它是一个依赖管理器,但它也是一个出色的 autoload generator

    如果你正确地添加了 composer.json,例如:

    "autoload": {
        "classmap": [
            "protected/",
        ]
    }
    

    在其中,它将自动生成一个完整的类映射数组,您可以从 vendor/composer/autoload_classmap.php 加载该数组。您所要做的就是确保数组的键是小写的,并且您可以匹配 1 对 1。只要确保记得在添加新类时调用“composer dump-autoload” .

    如果你这样做,考虑只加载完整的自动加载器(vendor/autoload.php),因为它会帮助整个 Yii 限制磁盘搜索。让 Yii 从中获益更多:

    $loader = require(__DIR__ . '/../vendor/autoload.php');
    Yii::$classMap = $loader->getClassMap();
    

    在调用 run() 函数之前,在 index.php 中。 这样 Yii 也可以在数组中查找类。

    对于您的问题,只需再次调用 $loader->getClassMap() 函数并将查找表的数组键小写即可。

    【讨论】:

      【解决方案2】:

      由于代码中的循环内有很多与文件系统相关的函数,因此所有发出的系统调用都会导致性能损失很大。你至少应该缓存你的方法的结果。

      Yii 核心开发者提出的this solution 可能是更好的方法:)

      【讨论】:

      • 是 YII 缓存已启用。但除此之外,它会对性能造成影响吗?有没有其他方法可以用 yii 做到这一点?我浏览了 yii 手册,但无法弄清楚。
      • 如果你的方法不使用它,Yii 缓存被启用是无关紧要的。我还用更好的解决方案更新了我的答案。
      • 感谢您的更新,但它根本没有帮助我。我已经推荐过一次了。我需要将类名和 get 参数都小写,并像在 e 函数中那样进行比较。
      • 呃。 ucfirst(strtolower($modelName)) 呢?不过,这对驼峰式类名没有帮助。
      • 如果我是你,我会使用 userstructureActivityLogdeviceModel 等名称的 API 调用。在模型名称上运行ucfirst(),让拼写错误成为用户的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-12
      • 2020-08-24
      • 2019-12-14
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 2013-10-20
      相关资源
      最近更新 更多