-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
I'm creating this issue because maybe it helps others which are interested in a similar solution and maybe there's interest in making the ide-helper code slightly more agnostic.
My scenario:
- I'm not using the Laravel "framework" directly
- I only use https://github.com/illuminate/database (and https://github.com/illuminate/container ) for integrating Eloquent in a legacy code base
If you never heard about this, you wouldn't know this really works and you can use Eloquent outside the framework.
But working with models without ide-helper is very annoying (also for static analysis like phpstan) so I was seeking a solution to make it possible to use ide-helper for two things:
- models phpdoc generation
- metadata generation for PhpStorm
I did not evaluate the generation of Facade data as I'm not using them.
To make the models
command work
- use of
base_path()
global helper from the framework
In\Barryvdh\LaravelIdeHelper\Console\ModelsCommand::loadModels
it uses the global helperbase_path()
which isn't available outside of the framework (it's defined in vendor/laravel/framework/src/Illuminate/Foundation/helpers.php)- My solution was to write my own global
base_path()
which I only load in the context of generating the models which creates me the correct path
- My solution was to write my own global
- Use of the
Config
service
Multiple times the$this->laravel['config']
service is access to load the configuration. However I'm not usingilluminate/config
either. I've created a one-shot anonymous class with my code which emulates the most basic methods to make this work. I used below code and and bound it to my container via$laravelContainer->instance('config', …)
; in below codeArr::get
can be used because of the dependencies of other packages toilluminate/support
:return new class($config) implements ArrayAccess { /** @var array */ private $config; public function __construct(array $config) { $this->config = $config; } public function get($key, $defaultVaue = null) { return Arr::get($this->config, $key, $defaultVaue); } public function offsetExists($offset) { throw new RuntimeException('Not implemented because we didn\'t need it yet'); } public function offsetGet($offset) { return $this->get($offset); } public function offsetSet($offset, $value) { throw new RuntimeException('Not implemented because we didn\'t need it yet'); } public function offsetUnset($offset) { throw new RuntimeException('Not implemented because we didn\'t need it yet'); } };
- Of course this means you need to somehow provide the configuration to the class which is custom in my case
- The final bootstrap to invoke the command was this:
$fileSystem = new Filesystem(); $command = new ModelsCommand($fileSystem); $command->setLaravel($laravelContainer); $command->run( new ArrayInput(['--write' => true, '--reset' => true]), new ConsoleOutput() );
To make the meta
command work
- I used the same config approach as outlined above
- The command uses the https://github.com/illuminate/view component to render the final metafile which I don't use, either. I therefore created a minimal anonymous class I passed to the
MetaCommand
constructor; it's looks like a hack but works :return new class() { public function make(string $view, array $bindings) { return new class($view, $bindings) { private $view; private $bindings; public function __construct(string $view, array $bindings) { $this->view = $view; $this->bindings = $bindings; } public function render(): string { $viewFile = base_path("vendor/barryvdh/laravel-ide-helper/resources/views/$this->view.php"); extract($this->bindings, EXTR_SKIP); ob_start(); require $viewFile; return ob_get_clean(); } }; } };
- Additionally, I've my own
::make()
method which I wanted to add to the generated file. I couldn't find a way to change\Barryvdh\LaravelIdeHelper\Console\MetaCommand::$methods
so I created my ownMyMetaCommand extends MetaCommand
class and just override theprotected $methods
property - After that, the final bootstrap call looks like this:
$fileSystem = new Filesystem(); $command = new MyMetaCommand($fileSystem, $viewClass, $configClass); $command->setLaravel($laravelContainer); $command->run( new ArrayInput([]), new ConsoleOutput() );
Finishing words
I didn't really knew upfront if I could make it work. I'm really happy it did, having known the ide-helper for years form real Laravel project I truly didn't wanted to miss it!
I think the only suggestions I would have:
- don't use
base_path()
inside\Barryvdh\LaravelIdeHelper\Console\ModelsCommand
, but pass it asstring $basePath
property to the commands constructor via\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider
- Provide a way to alter
\Barryvdh\LaravelIdeHelper\Console\MetaCommand::$methods
once the command is created. - Unsolved: in
\Barryvdh\LaravelIdeHelper\Console\ModelsCommand::createPhpDocs
the@mixin \Eloquent
is harcoded. I'm not even using Facades so if I still would would the mixin I would need them to point both the
Eloquent\Builderand
Query\Builder`; I left it as it for now
Otherwise: really very great package and I hope I continues to work also on the standalone versions in the future.
PS: feel free to close the issue, I merely wanted to document it for my future self/others