如何获得Laravel中所有型号的列表?

Tom*_*las 3 php mysql sql laravel eloquent

我想在Laravel项目中找到所有模型的列表,数据库表作为备份.

我想这样做是为了构建一个仪表板,显示所有模型中的数据随时间变化的方式,IE是否存在用户模型,过去90天每天添加或修改了多少用户.

Jef*_*eff 11

我会浏览你的文件系统并从你的模型文件夹中提取所有的php文件.我将我的模型保存在app/Models文件夹中,如下所示:

$path = app_path() . "/Models";

function getModels($path){
    $out = [];
    $results = scandir($path);
    foreach ($results as $result) {
        if ($result === '.' or $result === '..') continue;
        $filename = $path . '/' . $result;
        if (is_dir($filename)) {
            $out = array_merge($out, getModels($filename));
        }else{
            $out[] = substr($filename,0,-4);
        }
    }
    return $out;
}

dd(getModels($path));
Run Code Online (Sandbox Code Playgroud)

我只是尝试了这个,它吐出了我所有模型的完整文件路径.您可以剥离字符串,使其仅显示命名空间和模型名称,如果这就是您要查找的内容.

  • 您可以使用`app_path('Models')`而不是在第一行连接一个字符串,Laravel方式也可以使用`File :: allFiles($ path)`而不是自己编写所有逻辑. (4认同)

Rib*_*eno 11

我想建议一种不同的方法,即使用PHP 反射,而不是依赖所有模型都驻留在名为 Model 的命名空间或目录中。

下面的代码示例收集了所有应用程序类,验证它们是否确实扩展了 Eloquent Model 类并且不是抽象的。

<?php

use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;

function getModels(): Collection
{
    $models = collect(File::allFiles(app_path()))
        ->map(function ($item) {
            $path = $item->getRelativePathName();
            $class = sprintf('\%s%s',
                Container::getInstance()->getNamespace(),
                strtr(substr($path, 0, strrpos($path, '.')), '/', '\\'));

            return $class;
        })
        ->filter(function ($class) {
            $valid = false;

            if (class_exists($class)) {
                $reflection = new \ReflectionClass($class);
                $valid = $reflection->isSubclassOf(Model::class) &&
                    !$reflection->isAbstract();
            }

            return $valid;
        });

    return $models->values();
}
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是这里最强大的选择。谢谢 (2认同)

小智 7

我正在寻找可读的内容,因此,我编写了这段代码来获取所有模型名称,并且您可以按照自己想要的方式格式化。

<?php

function getModelNames(): array
{
    $path = app_path('Models') . '/*.php';
    return collect(glob($path))->map(fn ($file) => basename($file, '.php'))->toArray();
}
Run Code Online (Sandbox Code Playgroud)


Lup*_*abs 6

请注意,这可能会遗漏引导期间不在范围内的模型。请参阅下面的编辑。

有一种方法可以在不迭代文件系统的情况下加载声明的模型。由于大多数模型是在引导后声明的,您可以get_declared_classes像这样调用和过滤模型命名空间的返回值(我的类在\App\Models命名空间中):

$models   = collect(get_declared_classes())->filter(function ($item) {
    return (substr($item, 0, 11) === 'App\Models\\');
});
Run Code Online (Sandbox Code Playgroud)

正如@ChronoFish 所提到的,此方法不会在所有情况下都拉出所有模型。

例如,这在引导生命周期的早期阶段根本不起作用,就像在服务提供商中一样。但即使在它工作时,它也可能会遗漏一些模型,具体取决于您的项目结构,因为并非所有类总是在范围内。对于我的测试项目,所有模型都已加载,但在更复杂的应用程序中,这可能会遗漏大量类。

谢谢你的评论!

我目前正在使用这样的东西:

        $appNamespace = Illuminate\Container\Container::getInstance()->getNamespace();
        $modelNamespace = 'Models';

        $models = collect(File::allFiles(app_path($modelNamespace)))->map(function ($item) use ($appNamespace, $modelNamespace) {
            $rel   = $item->getRelativePathName();
            $class = sprintf('\%s%s%s', $appNamespace, $modelNamespace ? $modelNamespace . '\\' : '',
                implode('\\', explode('/', substr($rel, 0, strrpos($rel, '.')))));
            return class_exists($class) ? $class : null;
        })->filter();
Run Code Online (Sandbox Code Playgroud)

$modelNamespace是针对那些为他们的模型拥有不同文件夹和命名空间的人(强烈推荐)或使用 Laravel 8+(这是新的默认值)的人。那些只使用 Laravel 7 或更低版本的默认值的人可以将其留空,但随后会拉入 app 目录中的所有类,而不仅仅是 Eloquent 模型。

在这种情况下,您可以通过像这样过滤列表来确保只获得模型:

$models->filter(
    function ($model) {
        return !is_subclass_of($model, Illuminate\Database\Eloquent\Model::class);
    }
);
Run Code Online (Sandbox Code Playgroud)

  • 我认为这只会给你实例化的类。它不会为您提供我认为是 OP 要求的项目的所有模型。 (2认同)

小智 5

根据主题答案:

<?php

use Illuminate\Support\Facades\File;

/**
 * Get Available models in app.
 * 
 * @return array $models
 */
public static function getAvailableModels()
{

    $models = [];
    $modelsPath = app_path('Models');
    $modelFiles = File::allFiles($modelsPath);
    foreach ($modelFiles as $modelFile) {
        $models[] = '\App\\' . $modelFile->getFilenameWithoutExtension();
    }

    return $models;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果应用程序有添加更多模型的服务提供商,则此答案会错过它们。(同样在应用程序开发人员决定对模型使用不同路径的情况下) (2认同)