is it possible with Laravel to get a list of all defined Models into an array in a project so that they could be iterated over in a loop ie
foreach ($models as $model) {
echo $model;
}
is it possible with Laravel to get a list of all defined Models into an array in a project so that they could be iterated over in a loop ie
foreach ($models as $model) {
echo $model;
}
If all your models are in a single directory, you can list files in this directory and then generate class names based on file names. I'm afraid that's the only option, as Laravel doesn't require declaring models anywhere - creating class is enough. Moreover, listing classes existing in given namespace won't work either, as some models might be implemented, just not loaded.
Try the following code:
<?php
$dir = '/path/to/model/directory';
$files = scandir($dir);
$models = array();
$namespace = 'Your\Model\Namespace\\';
foreach($files as $file) {
//skip current and parent folder entries and non-php files
if ($file == '.' || $file == '..' || !preg_match('\.php', $file)) continue;
$models[] = $namespace . preg_replace('\.php$', '', $file);
}
print_r($models);
I know this answer is pretty late, but could be good if someone is trying to find solution for something similar.
To identify list of classes in my project, I simply defined this small function that helps to get classes at runtime with the help of \File Facade that returns SplFileInfo object array
/**
* @param $dir
*/
function getClassesList($dir)
{
$classes = \File::allFiles($dir);
foreach ($classes as $class) {
$class->classname = str_replace(
[app_path(), '/', '.php'],
['App', '\\', ''],
$class->getRealPath()
);
}
return $classes;
}
Usage of above function in Laravel
$classes = getClassesList(app_path('Models'));
// assuming all your models are present in Models directory
Here's a Laravel helper I'm using in production:
if (!function_exists('app_models')) {
function app_models($path = null, $base_model = null, bool $with_abstract = false)
{
// set up this filesystem disk in your config/filesystems file
// this is just pointing to the app/ directory using the local driver
$disk = Storage::disk('app');
return collect($disk->allFiles($path))
->map(function ($filename) use ($disk) {
return get_class_from_file($disk->path($filename));
})
->filter(function ($class) use ($base_model, $with_abstract) {
$ref = new ReflectionClass($class);
if ($ref->isAbstract() && !$with_abstract) return false;
return $ref->isSubclassOf(
$base_model ?? \Illuminate\Database\Eloquent\Model::class
);
});
}
}
Use it like this:
// all models in the app dir, recursively
$models = app_models();
// all models in the app/Models dir, recursively
$models = app_models('Models');
// same as above, except this will only show you the classes that are a subclass of the given model
$models = app_models('Models', App\Model::class);
// same again, but including abstract class models
$models = app_models('Models', App\Model::class, true);
Here's the helper for converting file paths into classes:
note: You have a lot of different options here. This is reliable, simple, and works well for me.
Here is another answer detailing some other options: Get class name from file
if (!function_exists('get_class_from_file')) {
function get_class_from_file($filepath)
{
// this assumes you're following PSR-4 standards, although you may
// still need to modify based on how you're structuring your app/namespaces
return (string)Str::of($filepath)
->replace(app_path(), '\App')
->replaceFirst('app', 'App')
->replaceLast('.php', '')
->replace('/', '\\');
}
}
You can make use of Laravel Processes. https://laravel.com/docs/10.x/processes
For windows users
$process = Process::path(app_path('Models'))->run('dir /b /a-d *.php');
dd($process->output());
For linux users
$process = Process::path(app_path('Models'))->run('ls *.php');
dd($process->output());
The above code will return a string containing the result. Hope this helps