How do I get a list of all models in Laravel?

I would navigate through your filesystem and pull out all of the php files from your models folder. I keep my models in the app/Models folder so something like this:

$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));

I just tried this and it spit out the full filepath of all of my models. You could strip the strings to make it only show the namespace and model name if thats what you are looking for.


Please be aware that this might miss models that have not been in scope during bootstrapping. Please see the edit below.

There is a way to load the declared models without iterating the file system. Since most of the models are declared after bootstrapping, you may call get_declared_classes and filter the return for your models' namespaces like this (my classes are in \App\Models namespace):

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

As @ChronoFish mentioned, this method does not pull up all models in all cases.

For example, this does not work at all in early stages of the bootstrap lifecycle like in service providers. But even when it is working, it might miss a few models, depending on your project's structure, as not all classes are always in scope. For my test project, all models were loaded, but in a more complex application, a significant number of classes may be missed by this.

Thanks for your comment!

I am currently using something like this:

        $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();

The $modelNamespace is for those who have a distinct folder and namespace for their models, which is highly recommended, or who are using Laravel 8+ where this is the new default. Those who just go with the defaults of Laravel 7 or lower can leave this empty, but will then pull in all classes in the app directory, not just Eloquent models.

In that case you can make sure you only get Models by filtering the list like this:

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

I would like to suggest a different approach by using PHP reflection instead of relying that all models will reside in a namespace or directory called Model.

The code sample below collects all the application classes, verifies if they actually extend the Eloquent Model class and are not abstract.

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