0

Is there a way to fetch all existing models in Laravel 4? The documentation says nothing about this and googling the issue didn't result in anything relevant.

I'm working on a feature in my current project that needs the ability to create a report of which assets there are or which customer has bought which asset at the company. For that, I'm creating a module that allows the user to specify what information goes on which worksheet (exports to Excel).

Let's say I have the following models (They all extend Eloquent):

  • Asset
  • Customer
  • Country
  • Keys
  • User

I only want the Asset and Customer model to be usable in the report. My idea is to give those a constant and check on that constant.

The only thing I'm bumping my head against is a way to fetch all the models that are defined in my Laravel application.

I know I could loop through the app/models directory or create an array somewhere but I'm looking for a better way of doing this. Does anyone happen to know how to achieve this?

MisterBla
  • 2,355
  • 1
  • 18
  • 29
  • Look at [this answer](http://stackoverflow.com/a/6671567/2629998) which shows a way to get all classes that extend a parent class (in your case it's `Eloquent`). –  Mar 28 '14 at 16:00
  • I would create a repository or service provider class to handle the functionality you describe. Then simply fetch the classes using Laravel's built-in IoC class. – Dave Mar 28 '14 at 16:06
  • @André `get_declared_classes()` does not list any model that is not called before. – MisterBla Mar 31 '14 at 07:09

1 Answers1

1

After some research, and asking around in the PHP Chatroom I came with the following solution:

First I retrieve all models from the /app/models directory, removing . and .. and trimming the extension off the file names and any leftover whitespace.
In my case this will work because I named the file after the classes.

private function getModels()
{
    return array_filter(scandir(app_path('models/')), function(&$val)
    {
        if($val != '.' && $val != '..')
        {
            $val = trim(str_replace('.php', '', $val));
            return class_exists($val);
        }
    });
}

Now I have all models I want, I need to filter which ones I want to have reported. On the models which I want to have reported, I implemented an interface called IReportable. I wanted to use an abstract class, but since PHP doesn't allow multiple inheritance I went with this method.

class MyModel extends Eloquent implements IReportable

Or in my case:

Class Asset extends BaseModel implements IReportable

With this, I can filter the models.

private function getReportableModels()
{
    return array_filter($this->getModels(), function($model)
    {
        return in_array('IReportable', class_implements($model, false));
    });
}
MisterBla
  • 2,355
  • 1
  • 18
  • 29