VOOZH about

URL: https://deepwiki.com/hypervel/devtool/5.1-model-and-factory-generation

⇱ Model and Factory Generation | hypervel/devtool | DeepWiki


Loading...
Menu

Model and Factory Generation

Purpose and Scope

This document details the make:model and make:factory commands, which generate Eloquent model classes and their associated factory classes for database testing and seeding. The ModelCommand serves as an orchestrator that can optionally invoke the FactoryCommand and other related generators. For seeder generation, see Seeder Generation. For the broader model system orchestration capabilities, see Model System Generators.


Command Overview

The model and factory generation system consists of two primary commands:

CommandClassPurposeDefault Output Location
make:modelHypervel\Devtool\Generator\ModelCommandGenerate Eloquent model classesapp/Models/*.php
make:factoryHypervel\Devtool\Generator\FactoryCommandGenerate model factory classesdatabase/factories/*.php

Both commands extend Hyperf\Devtool\Generator\GeneratorCommand, inheriting the base stub processing and file generation functionality described in Generator Command Architecture.

Sources: src/Generator/ModelCommand.php14-19 src/Generator/FactoryCommand.php11-16


Model Generation Architecture

Command Execution Flow


Diagram: ModelCommand Execution Pipeline

Sources: src/Generator/ModelCommand.php31-66


Model Stub Template Structure

The model stub template src/Generator/stubs/model.stub uses placeholder substitution to generate the final model class:

PlaceholderReplacement ValueDetermined By
%NAMESPACE%Target namespace (default: App\Models)getDefaultNamespace() method
%CLASS%Model class nameUser input argument
%USES%Base model class to extendConfiguration or Hypervel\Database\Eloquent\Model

Generated Model Structure:

<?php

declare(strict_types=1);

namespace App\Models;

use Hypervel\Database\Eloquent\Model;

class User extends Model
{
 protected array $fillable = [];
 protected array $casts = [];
}

The generated model includes:

  • Strict typing declaration for PHP 8.2+ compatibility
  • $fillable array for mass assignment protection
  • $casts array for attribute type casting

Sources: src/Generator/stubs/model.stub1-21 src/Generator/ModelCommand.php71-78


Model Command Options

The ModelCommand supports extensive orchestration through command-line options:

OptionShortTypePurpose
--all-aFlagGenerate migration, seeder, factory, controller, policy, and requests
--factory-fFlagGenerate associated factory class
--migration-mFlagGenerate database migration
--seed-sFlagGenerate seeder class
--controller-cFlagGenerate controller class
--resource-rFlagGenerate resource controller with CRUD methods
--apiFlagGenerate API resource controller
--policyFlagGenerate policy class for authorization
--requests-RFlagGenerate form request validation classes
--forceFlagOverwrite existing model file
--namespace-NValueCustom namespace for the model

Sources: src/Generator/ModelCommand.php90-105


ModelCommand Option Processing Logic

The --all option cascade mechanism:


Diagram: --all Option Cascade

When --all is provided, it activates all generation options except --api and --requests, creating a complete CRUD scaffold.

Sources: src/Generator/ModelCommand.php35-42


Factory Generation Architecture

FactoryCommand Structure


Diagram: FactoryCommand Execution Flow

Sources: src/Generator/FactoryCommand.php11-91


Factory Stub Template Structure

The factory stub src/Generator/stubs/factory.stub generates factories that extend Hypervel\Database\Eloquent\Factories\Factory:

PlaceholderReplacement ValueDetermined By
%MODEL%Model class name (without namespace)Inferred from factory name or --model option
%MODEL_NAMESPACE%Fully qualified model class namegetModelNamespace() method

Generated Factory Structure:

<?php

declare(strict_types=1);

namespace Database\Factories;

use App\Models\User;
use Hypervel\Database\Eloquent\Factories\Factory;

/**
 * @extends Factory<User>
 */
class UserFactory extends Factory
{
 public function definition(): array
 {
 return [
 //
 ];
 }
}

Key features:

  • Generic type annotation @extends Factory<User> for IDE support
  • definition() method returns array of default model attributes
  • Namespace resolution automatically determines model location

Sources: src/Generator/stubs/factory.stub1-27 src/Generator/FactoryCommand.php40-58


Factory-Model Association Logic

The FactoryCommand determines the associated model through this resolution chain:


Diagram: Model Resolution in FactoryCommand

Sources: src/Generator/FactoryCommand.php42-50 src/Generator/FactoryCommand.php30-35


Model-Factory Orchestration

Orchestration from ModelCommand

When the ModelCommand is invoked with the --factory option, it orchestrates factory generation:


Diagram: Model-to-Factory Orchestration Sequence

Sources: src/Generator/ModelCommand.php44-46 src/Generator/ModelCommand.php110-118


createFactory() Implementation

The createFactory() method in ModelCommand:

protected function createFactory()
{
 $factory = Str::studly($this->input->getArgument('name'));

 $this->call('make:factory', [
 'name' => "{$factory}Factory",
 '--force' => $this->input->getOption('force'),
 ]);
}

Processing steps:

  1. Extract model name from input argument
  2. Convert to StudlyCase using Hyperf\Stringable\Str::studly()
  3. Append "Factory" suffix to create factory class name
  4. Invoke make:factory command via internal call() method
  5. Propagate --force option to allow overwrites if specified

Sources: src/Generator/ModelCommand.php110-118


Internal Command Invocation

The call() method enables command-to-command orchestration:

protected function call(string $command, array $parameters = []): int
{
 return $this->getApplication()->doRun(
 new ArrayInput(array_merge(['command' => $command], $parameters)),
 $this->output
 );
}

This mechanism:

  • Creates ArrayInput instance with command name and parameters
  • Invokes application's doRun() method directly
  • Shares the same output interface for consistent console feedback
  • Returns exit code for error handling

Sources: src/Generator/ModelCommand.php192-198


Configuration and Customization

Model Configuration Options

The ModelCommand supports configuration overrides via the getConfig() method:

Configuration KeyPurposeDefault Value
stubCustom stub template path__DIR__ . '/stubs/model.stub'
namespaceDefault model namespaceApp\Models
usesBase model class to extendHypervel\Database\Eloquent\Model

Usage in code:

// In replaceClass() - Line 75
$uses = $this->getConfig()['uses'] ?? \Hypervel\Database\Eloquent\Model::class;

// In getStub() - Line 82
return $this->getConfig()['stub'] ?? __DIR__ . '/stubs/model.stub';

// In getDefaultNamespace() - Line 87
return $this->getConfig()['namespace'] ?? 'App\Models';

Sources: src/Generator/ModelCommand.php75-88


Factory Configuration Options

The FactoryCommand supports similar configuration:

Configuration KeyPurposeDefault Value
stubCustom stub template path__DIR__ . '/stubs/factory.stub'
pathOutput directory for factoriesdatabase/factories
model_namespaceModel namespace for resolutionApp\Models

Path resolution in FactoryCommand:

protected function getPath(string $name): string
{
 $path = $this->getConfig()['path'] ?? 'database/factories';
 return BASE_PATH . "/{$path}/{$name}.php";
}

Note that FactoryCommand returns an empty string from getDefaultNamespace() because factories are stored in a flat directory structure without namespace subdirectories.

Sources: src/Generator/FactoryCommand.php25-28 src/Generator/FactoryCommand.php71-76 src/Generator/FactoryCommand.php78-81


Class Name Qualification Differences

A critical architectural difference between the two commands is their qualifyClass() behavior:


Diagram: Class Name Qualification Strategy

Explanation:

  • ModelCommand: Uses inherited qualifyClass() which prepends namespace (e.g., App\Models\User)
  • FactoryCommand: Overrides to return the name unchanged because factories use flat file structure without namespace subdirectories

Sources: src/Generator/FactoryCommand.php63-66


Usage Examples

Basic Model Generation


Model with Factory


Complete CRUD Scaffold


Standalone Factory Generation



File Location Summary

Generated File TypeDefault PathConfigurable Via
Modelapp/Models/{ClassName}.phpModelCommand config namespace key
Factorydatabase/factories/{ClassName}Factory.phpFactoryCommand config path key

Both commands respect the BASE_PATH constant for root directory resolution.

Sources: src/Generator/ModelCommand.php85-88 src/Generator/FactoryCommand.php71-76