Skip to content

Commit

Permalink
Use dynamic app namespace in Eloquent Factory instead of static App\
Browse files Browse the repository at this point in the history
  • Loading branch information
0xb4lint committed Nov 12, 2020
1 parent 72ea7ba commit 2341dfe
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 13 deletions.
12 changes: 6 additions & 6 deletions src/Illuminate/Database/Console/Factories/FactoryMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ protected function buildClass($name)

$model = class_basename($namespaceModel);

if (Str::startsWith($namespaceModel, 'App\\Models')) {
$namespace = Str::beforeLast('Database\\Factories\\'.Str::after($namespaceModel, 'App\\Models\\'), '\\');
if (Str::startsWith($namespaceModel, $this->rootNamespace().'Models')) {
$namespace = Str::beforeLast('Database\\Factories\\'.Str::after($namespaceModel, $this->rootNamespace().'Models\\'), '\\');
} else {
$namespace = 'Database\\Factories';
}
Expand Down Expand Up @@ -99,7 +99,7 @@ protected function buildClass($name)
*/
protected function getPath($name)
{
$name = (string) Str::of($name)->replaceFirst('App\\', '')->finish('Factory');
$name = (string) Str::of($name)->replaceFirst($this->rootNamespace(), '')->finish('Factory');

return $this->laravel->databasePath().'/factories/'.str_replace('\\', '/', $name).'.php';
}
Expand All @@ -116,17 +116,17 @@ protected function guessModelName($name)
$name = substr($name, 0, -7);
}

$modelName = $this->qualifyModel(Str::after($name, 'App\\'));
$modelName = $this->qualifyModel(Str::after($name, $this->rootNamespace()));

if (class_exists($modelName)) {
return $modelName;
}

if (is_dir(app_path('Models/'))) {
return 'App\Models\Model';
return $this->rootNamespace().'Models\Model';
}

return 'App\Model';
return $this->rootNamespace().'Model';
}

/**
Expand Down
20 changes: 14 additions & 6 deletions src/Illuminate/Database/Eloquent/Factories/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Application;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\ForwardsCalls;
Expand Down Expand Up @@ -626,10 +627,13 @@ public function modelName()
{
$resolver = static::$modelNameResolver ?: function (self $factory) {
$factoryBasename = Str::replaceLast('Factory', '', class_basename($factory));
$rootNamespace = Container::getInstance()
->make(Application::class)
->getNamespace();

return class_exists('App\\Models\\'.$factoryBasename)
? 'App\\Models\\'.$factoryBasename
: 'App\\'.$factoryBasename;
return class_exists($rootNamespace.'Models\\'.$factoryBasename)
? $rootNamespace.'Models\\'.$factoryBasename
: $rootNamespace.$factoryBasename;
};

return $this->model ?: $resolver($this);
Expand Down Expand Up @@ -700,9 +704,13 @@ protected function withFaker()
public static function resolveFactoryName(string $modelName)
{
$resolver = static::$factoryNameResolver ?: function (string $modelName) {
$modelName = Str::startsWith($modelName, 'App\\Models\\')
? Str::after($modelName, 'App\\Models\\')
: Str::after($modelName, 'App\\');
$rootNamespace = Container::getInstance()
->make(Application::class)
->getNamespace();

$modelName = Str::startsWith($modelName, $rootNamespace.'Models\\')
? Str::after($modelName, $rootNamespace.'Models\\')
: Str::after($modelName, $rootNamespace);

return static::$namespace.$modelName.'Factory';
};
Expand Down
30 changes: 29 additions & 1 deletion tests/Database/DatabaseEloquentFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,20 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Foundation\Application;
use Mockery;
use PHPUnit\Framework\TestCase;

class DatabaseEloquentFactoryTest extends TestCase
{
protected function setUp(): void
{
Container::getInstance()->singleton(\Faker\Generator::class, function ($app, $parameters) {
$container = Container::getInstance();
$container->singleton(\Faker\Generator::class, function ($app, $parameters) {
return \Faker\Factory::create('en_US');
});
$container->instance(Application::class, $app = Mockery::mock(Application::class));
$app->shouldReceive('getNamespace')->andReturn('App\\');

$db = new DB;

Expand Down Expand Up @@ -81,7 +86,11 @@ public function createSchema()
*/
protected function tearDown(): void
{
Mockery::close();

$this->schema()->drop('users');

Container::setInstance(null);
}

public function test_basic_model_can_be_created()
Expand Down Expand Up @@ -326,6 +335,25 @@ public function test_resolve_nested_model_factories()
}
}

public function test_resolve_non_app_nested_model_factories()
{
Container::getInstance()->instance(Application::class, $app = Mockery::mock(Application::class));
$app->shouldReceive('getNamespace')->andReturn('Foo\\');

Factory::useNamespace('Factories\\');

$resolves = [
'Foo\\Bar' => 'Factories\\BarFactory',
'Foo\\Models\\Bar' => 'Factories\\BarFactory',
'Foo\\Models\\Nested\\Bar' => 'Factories\\Nested\\BarFactory',
'Foo\\Models\\Really\\Nested\\Bar' => 'Factories\\Really\\Nested\\BarFactory',
];

foreach ($resolves as $model => $factory) {
$this->assertEquals($factory, Factory::resolveFactoryName($model));
}
}

public function test_model_has_factory()
{
Factory::guessFactoryNamesUsing(function ($model) {
Expand Down

0 comments on commit 2341dfe

Please sign in to comment.