changeset 34:f65ab84ee47f default

merge with codex
author luka
date Wed, 10 Sep 2025 21:00:47 -0400
parents a9ff874afdbd (current diff) 93adaad3ca65 (diff)
children 55d2e5c5dad9
files
diffstat 43 files changed, 2044 insertions(+), 409 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,9 @@
+syntax: glob
+vendor
+*.env
+*.env.backup
+*.env.production
+.php-cs-fixer.cache
+*.aichat
+tags
+
--- a/.php-cs-fixer.cache	Sat Dec 02 10:20:32 2023 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-{"php":"8.2.12","version":"3.19.1","indent":"    ","lineEnding":"\n","rules":{"align_multiline_comment":true,"array_syntax":true,"backtick_to_shell_exec":true,"binary_operator_spaces":true,"blank_line_before_statement":{"statements":["return"]},"cast_spaces":true,"class_attributes_separation":{"elements":{"method":"one"}},"class_definition":{"single_line":true},"class_reference_name_casing":true,"clean_namespace":true,"concat_space":true,"curly_braces_position":{"allow_single_line_anonymous_functions":true,"allow_single_line_empty_anonymous_classes":true},"declare_parentheses":true,"echo_tag_syntax":true,"empty_loop_body":{"style":"braces"},"empty_loop_condition":true,"fully_qualified_strict_types":true,"function_typehint_space":true,"general_phpdoc_tag_rename":{"replacements":{"inheritDocs":"inheritDoc"}},"global_namespace_import":{"import_classes":false,"import_constants":false,"import_functions":false},"include":true,"increment_style":true,"integer_literal_case":true,"lambda_not_used_import":true,"linebreak_after_opening_tag":true,"magic_constant_casing":true,"magic_method_casing":true,"method_argument_space":{"on_multiline":"ignore"},"native_function_casing":true,"native_function_type_declaration_casing":true,"no_alias_language_construct_call":true,"no_alternative_syntax":true,"no_binary_string":true,"no_blank_lines_after_phpdoc":true,"no_empty_comment":true,"no_empty_phpdoc":true,"no_empty_statement":true,"no_extra_blank_lines":{"tokens":["attribute","case","continue","curly_brace_block","default","extra","parenthesis_brace_block","square_brace_block","switch","throw","use"]},"no_leading_namespace_whitespace":true,"no_mixed_echo_print":true,"no_multiline_whitespace_around_double_arrow":true,"no_null_property_initialization":true,"no_short_bool_cast":true,"no_singleline_whitespace_before_semicolons":true,"no_spaces_around_offset":true,"no_superfluous_phpdoc_tags":{"remove_inheritdoc":true},"no_trailing_comma_in_singleline":true,"no_unneeded_control_parentheses":{"statements":["break","clone","continue","echo_print","others","return","switch_case","yield","yield_from"]},"no_unneeded_curly_braces":{"namespaces":true},"no_unneeded_import_alias":true,"no_unset_cast":true,"no_unused_imports":true,"no_useless_concat_operator":true,"no_useless_nullsafe_operator":true,"no_whitespace_before_comma_in_array":true,"normalize_index_brace":true,"nullable_type_declaration_for_default_null_value":{"use_nullable_type_declaration":false},"object_operator_without_whitespace":true,"operator_linebreak":{"only_booleans":true},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"alpha"},"php_unit_fqcn_annotation":true,"php_unit_method_casing":true,"phpdoc_align":true,"phpdoc_annotation_without_dot":true,"phpdoc_indent":true,"phpdoc_inline_tag_normalizer":true,"phpdoc_no_access":true,"phpdoc_no_alias_tag":true,"phpdoc_no_package":true,"phpdoc_no_useless_inheritdoc":true,"phpdoc_order":{"order":["param","return","throws"]},"phpdoc_return_self_reference":true,"phpdoc_scalar":true,"phpdoc_separation":true,"phpdoc_single_line_var_spacing":true,"phpdoc_summary":true,"phpdoc_tag_type":{"tags":{"inheritDoc":"inline"}},"phpdoc_to_comment":true,"phpdoc_trim":true,"phpdoc_trim_consecutive_blank_line_separation":true,"phpdoc_types":true,"phpdoc_types_order":{"null_adjustment":"always_last","sort_algorithm":"none"},"phpdoc_var_without_name":true,"semicolon_after_instruction":true,"simple_to_complex_string_variable":true,"single_class_element_per_statement":true,"single_import_per_statement":true,"single_line_comment_spacing":true,"single_line_comment_style":{"comment_types":["hash"]},"single_line_throw":true,"single_quote":true,"single_space_around_construct":true,"space_after_semicolon":{"remove_in_empty_for_expressions":true},"standardize_increment":true,"standardize_not_equals":true,"switch_continue_to_break":true,"trailing_comma_in_multiline":true,"trim_array_spaces":true,"types_spaces":true,"unary_operator_spaces":true,"whitespace_after_comma_in_array":true,"yoda_style":true,"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"compact_nullable_typehint":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_braces":true,"no_blank_lines_after_class_opening":true,"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"return_type_declaration":true,"short_scalar_cast":true,"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_spaces_inside_parenthesis":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_line_after_imports":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true},"hashes":{"src\/Generator\/Route\/RouteGenerator.php":"02bf90516b88a1b0b00a84afb10d8a45","src\/Generator\/Controller\/ControllerGenerator.php":"717cdb9124e7e4afe4a28e17b94089e9","src\/Generator\/Model\/ModelGenerator.php":"31743678bf017f63680db19e9682df45","src\/Generator\/Generator.php":"c7cd32166a24be83f6575d33f6c4ba80","src\/Generator\/Requests\/UpdateRequestGenerator.php":"63475513d258b0727637db19629d4ac6","src\/Generator\/Requests\/RequestGenerator.php":"93fbc04a1ea18b794ee7f24902ae9cc1","src\/Generator\/Requests\/StoreRequestGenerator.php":"42bac2b426288d9a08216dfc5fe45faf","src\/Generator\/BaseGenerator.php":"c0aa37a727252383bc28aebf7a0019ec","src\/MagicForgerServiceProvider.php":"00c1321ad894d1e0807036dbe9114bf2","src\/Replacer\/Replacer.php":"501a0ebcf606a7602973b6033ee54b8e","src\/Replacer\/TableReplacer.php":"dc289802665136521abf6ffea0203732","src\/ConfigHelper.php":"c11480fee67c40ca948c38c14bed7d16"}}
\ No newline at end of file
--- a/.vimrc	Sat Dec 02 10:20:32 2023 -0500
+++ b/.vimrc	Wed Sep 10 21:00:47 2025 -0400
@@ -8,6 +8,7 @@
 "set number
 nnoremap <Leader>cc :set colorcolumn=80<cr>
 nnoremap <Leader>ncc :set colorcolumn-=80<cr>
+nnoremap <C-l> :ALECodeAction <cr>
 set mouse=a
 
 function! FixPhpFiles()
@@ -27,23 +28,22 @@
 " Committing commands
 map <C-k> :wa<CR>:!hg addremove && hg commit <CR>
 
-" Git commands, for now don't port to hg
-" function! GitDiffCached()
-"   let files = system('git diff --cached --name-only')
-" 
-"   if v:shell_error
-"     echo "Error running git diff"
-"     return
-"   endif
-" 
-"   let filelist = split(files, "\n")
-"   let chosen_file = inputlist(filelist)
-" 
-"   if chosen_file != -1
-" 		let cmd = 'tabnew ' . filelist[chosen_file]
-"     execute cmd
-"   endif
-" endfunction
-" 
-" execute "set <M-d>=\033d"
-" map <M-d> :call GitDiffCached()<CR>
+
+
+function! SendBufferToProgram()
+    " Create a temporary file
+    let temp_file = tempname()
+    
+    " Write current buffer to the temporary file
+    exe "write! " . temp_file
+    
+    " Send the content of the temporary file to your program
+    " Replace <your_program> with the actual command to run your program
+    let command = "cat " . temp_file . " | <your_program>"
+    
+    " Execute the command
+    call system(command)
+    
+    " Optionally, delete the temporary file if not needed
+    call delete(temp_file)
+endfunction
--- a/composer.json	Sat Dec 02 10:20:32 2023 -0500
+++ b/composer.json	Wed Sep 10 21:00:47 2025 -0400
@@ -1,20 +1,21 @@
 {
-    "name": "wizzard/magicforger",
+    "name": "wizard/magicforger",
+		"version": "1.0.0",
     "description": "Magically makes all your CRUD in a smart and repeatable way.",
-		"version": "dev-default",
     "autoload": {
         "psr-4": {
-						"Wizzard\\MagicForger\\":"src/"
+						"Wizard\\MagicForger\\":"src/"
         }
     },
     "minimum-stability": "stable",
     "require": {
-        "laravel/framework": ">=10.3"
+        "laravel/framework": ">=12",
+        "doctrine/dbal": "*"
     },
 		"extra": {
     	"laravel": {
     	    "providers": [
-						"Wizzard\\MagicForger\\MagicForgerServiceProvider"
+						"Wizard\\MagicForger\\MagicForgerServiceProvider"
     	    ]
     	}
 		}
--- a/src/ConfigHelper.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/ConfigHelper.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,6 +1,8 @@
 <?php
 
-namespace Wizzard\MagicForger;
+namespace Wizard\MagicForger;
+
+use Illuminate\Support\Collection;
 
 class ConfigHelper
 {
@@ -11,32 +13,28 @@
     public const CONFIG_FILE_NAME = 'mf_config.php';
 
     // Config path variable
-    public static $config_path;
+    public static string $config_path;
 
     /**
-     * Set up configuration path
-     *
-     * @param string $base_path
+     * Set up configuration path.
      */
-    public static function setup_config_path(string $base_path)
+    public static function setup_config_path(string $base_path): void
     {
         self::$config_path = $base_path.'/'.self::CONFIG_FILE_NAME;
     }
 
     /**
-     * Get configuration path
-     *
-     * @return string
+     * Get configuration path.
      */
-    protected static function get_config_path()
+    protected static function get_config_path(): string
     {
         return self::$config_path;
     }
 
     /**
-     * Write configuration into a file
+     * Write configuration into a file.
      */
-    public static function write_config()
+    public static function write_config(): void
     {
         $path = self::get_config_path();
         $str = '<?php
@@ -48,18 +46,18 @@
     }
 
     /**
-     * Read configuration from a file
+     * Read configuration from a file.
      */
-    public static function read_config()
+    public static function read_config(): void
     {
         $path = self::get_config_path();
         self::$config = include $path;
     }
 
     /**
-     * Print configuration
+     * Print configuration.
      */
-    public static function print_config()
+    public static function print_config(): void
     {
         self::varexport(self::$config);
     }
@@ -71,11 +69,10 @@
      *
      * @see https://www.php.net/manual/en/function.var-export.php
      *
-     * @param mixed $expression
-     * @param boolean $return
-     * @return mixed
+     * @param  bool  $return
+     * @return string|string[]|null
      */
-    public static function varexport($expression, $return = false)
+    public static function varexport(mixed $expression, $return = false): string|array|null
     {
         $export = var_export($expression, true);
         $patterns = [
@@ -90,31 +87,47 @@
         } else {
             echo $export;
         }
+
+        return null;
     }
 
     /**
-     * Format the given file
-     *
-     * @param string $path
+     * Format the given file.
      */
-    protected static function format_file(string $path)
+    protected static function format_file(string $path): void
     {
         exec('php-cs-fixer fix '.$path);
     }
 
     /**
-     * Set up tables
+     * Set up tables.
      */
-    public static function set_up_tables()
+    public static function set_up_tables(): Collection
     {
         $schema = \DB::connection()->getDoctrineSchemaManager();
-        // get all the tables available in the database
         $tables = collect($schema->listTableNames())->all();
+        $table_foreign_keys = [];
+        foreach ($tables as $table) {
+            $table_foreign_keys[$table] = $schema->listTableForeignKeys($table);
+        }
 
         $insert_tables = [];
         foreach ($tables as $table) {
             $columns = [];
-            $table_columns = $schema->introspectTable($table)->getColumns();
+            $table_columns = $schema->listTableColumns($table);
+
+            // Initiate new arrays for foreign keys
+            $foreign_keys = [];
+            $foreign_keys_reverse = [];
+
+            // Check foreign key references from this table
+            $foreign_keys_list = $table_foreign_keys[$table];
+            foreach ($foreign_keys_list as $fk) {
+                $foreign_keys[$fk->getLocalColumns()[0]] = [
+                    'foreign_table' => $fk->getForeignTableName(),
+                    'foreign_column' => $fk->getForeignColumns()[0],
+                ];
+            }
 
             foreach ($table_columns as $column) {
                 $full_class = get_class($column->getType());
@@ -122,37 +135,52 @@
                 $class_name = end($class_parts);
 
                 $columns[$column->getName()] = [
-                                'type' => $class_name,
-                                'should_insert' => [
-                                        'controller' => true,
-                                        'model' => true,
-                                        'requests' => true,
-                                        'views' => true,
-                                      ],
-                                ];
+                    'type' => $class_name,
+                    'should_insert' => [
+                        'controller' => true,
+                        'model' => true,
+                        'requests' => true,
+                        'views' => true,
+                    ],
+                ];
             }
-
+            // Check foreign key references to this table
+            foreach ($tables as $other_table) {
+                if ($other_table != $table) {
+                    $foreign_keys_list = $table_foreign_keys[$other_table];
+                    foreach ($foreign_keys_list as $fk) {
+                        if ($fk->getForeignTableName() == $table) {
+                            $foreign_keys_reverse[] = [
+                                'table' => $other_table,
+                                'column' => $fk->getLocalColumns()[0],
+                            ];
+                        }
+                    }
+                }
+            }
             $insert_tables[$table] = [];
             $insert_tables[$table]['columns'] = $columns;
+            $insert_tables[$table]['foreign_keys'] = $foreign_keys; // Foreign keys FROM this table
+            $insert_tables[$table]['foreign_keys_reverse'] = $foreign_keys_reverse; // Foreign keys TO this table
             $insert_tables[$table]['type'] = 'default';
         }
-        // Merge the new tables configuration into the initial config
+
         self::merge_array_priority(self::$config['tables'], $insert_tables);
 
         return $tables;
     }
 
     /**
-     * Merge two arrays and ensure priority values do not get overwritten
+     * Merge two arrays and ensure priority values do not get overwritten.
      *
-     * @param array $priority
-     * @param array $merged
+     * @param  array  $priority
+     * @param  array  $merged
      */
-    private static function merge_array_priority(&$priority, $merged)
+    private static function merge_array_priority(&$priority, $merged): void
     {
         foreach ($merged as $key => $value) {
             // if the priority key is not set, automatically add the merged values
-            if (!isset($priority[$key])) {
+            if (! isset($priority[$key])) {
                 $priority[$key] = $value;
             } else {
                 // if the value is an array recursively merge with priority
--- a/src/Generator/BaseGenerator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/BaseGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,242 +1,203 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator;
+namespace Wizard\MagicForger\Generator;
 
-use DB;
 use Illuminate\Console\GeneratorCommand;
+use Illuminate\Support\Facades\Schema;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\OutputInterface;
-use Wizzard\MagicForger\Replacer\Replacer;
-use Wizzard\MagicForger\Replacer\TableReplacer;
+use Wizard\MagicForger\Replacer\Replacer;
+use Wizard\MagicForger\Replacer\TableReplacer;
 
 abstract class BaseGenerator extends GeneratorCommand
 {
     use Replacer;
     use TableReplacer;
 
-    /**
-     * The schema of the database.
-     *
-     * @var string
-     */
-    protected $schema;
+    protected $schema = null;
+
+    protected $tables = null;
 
-    /**
-     * The tables available in the schema.
-     *
-     * @var array
-     */
-    protected $tables;
+    protected $currentTable = null;
 
-    /**
-     * The current Table being used.
-     *
-     * @var table
-     */
-    protected $currentTable;
+    protected static $cached_snippets = [];
 
-    /**
-     * Execute the console command.
-     */
     public function handle()
     {
-        // First we need to ensure that the table exists, then we can
-        if (!$this->tableExists($this->getTableInput())) {
+
+        if (! $this->tableExists($this->getTableInput())) {
             $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
 
             return false;
         }
 
         $this->setCurrentTable($this->getTableInput());
-
         $path = $this->getPath();
-
         $file = $this->getFile($path);
-
         $file = $this->apply_replacements($file);
-
         $file = $this->apply_inserts($file);
-
         $this->makeDirectory($path);
-
         $this->files->put($path, $this->sortImports($file));
-
         $this->format_file($path);
-
-        $info = $this->type;
-
-        $this->components->info(sprintf('%s [%s] created successfully.', $info, $path));
+        $this->components->info(sprintf('%s [%s] created successfully.', $this->type, $path));
     }
 
-    /**
-     * Override the original so that we can prompt for a table with autocomplete.
-     */
-    protected function promptForMissingArguments(InputInterface $input, OutputInterface $output)
+    protected function promptForMissingArguments(InputInterface $input, OutputInterface $output): void
     {
         $prompted = false;
         if (is_null($input->getArgument('table'))) {
             $prompted = true;
             $table = null;
-            while (null === $table) {
+            while ($table === null) {
                 $table = $this->components->askWithCompletion(
                     'What Table should we use?',
                     $this->possibleTables()
                 );
             }
-
             $input->setArgument('table', $table);
         }
 
         parent::promptForMissingArguments($input, $output);
 
-        // This will get missed if we prompt here but not in the parent
         if ($prompted) {
             $this->afterPromptingForMissingArguments($input, $output);
         }
     }
 
-    /**
-     * Get the console command arguments.
-     *
-     * @return array
-     */
-    protected function getArguments()
+    protected function getArguments(): array
     {
         return [
             ['table', InputOption::VALUE_REQUIRED, 'The table to generate files for.'],
         ];
     }
 
-    /**
-     * Prompt for missing input arguments using the returned questions.
-     *
-     * @return array
-     */
-    protected function promptForMissingArgumentsUsing()
+    protected function promptForMissingArgumentsUsing(): array
     {
-        return [
-        ];
+        return [];
     }
 
-    /**
-     * Get the console command options.
-     *
-     * @return array
-     */
-    protected function getOptions()
+    protected function getOptions(): array
     {
         return [
             ['fresh', 'f', InputOption::VALUE_NONE, 'Start from the stub or use existing if possible.'],
         ];
     }
 
-    /**
-     * Interact further with the user if they were prompted for missing arguments.
-     *
-     * @return void
-     */
-    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output)
+    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void
     {
+        // Additional logic after prompting goes here
     }
 
-    /**
-     * Determines if the file exists.
-     */
     protected function fileExists(string $path): bool
     {
         return $this->files->exists($path);
     }
 
-    /**
-     * Gets the file that will be worked on. If there is already an existing file
-     * then we can open that. However if we are forcing the operation, then we
-     * will start with an empty stub.
-     */
-    protected function getFile($name)
+    protected function getFile($name): string
     {
-        if (!($this->hasOption('fresh')
-             && $this->option('fresh'))
-             && $this->fileExists($name)) {
-            // Working with an existing file
+        if (! ($this->hasOption('fresh') && $this->option('fresh')) && $this->fileExists($name)) {
             return $this->files->get($name);
         }
 
-        // Working with a stub
         return $this->files->get($this->getStub());
     }
 
-    /**
-     * Get the desired class table from the input.
-     *
-     * @return string
-     */
-    protected function getTableInput()
+    protected function getTableInput(): string
     {
         return trim($this->argument('table'));
     }
 
-    /**
-     * Determines if the table exists in the current database.
-     */
     protected function tableExists(string $table_name): bool
     {
         return in_array($table_name, $this->getTables());
     }
 
-    /**
-     * Get a list of possible table names.
-     */
-    protected function possibleTables()
+    protected function possibleTables(): array
     {
         return $this->getTables();
     }
 
-    /**
-     * Get the tables in the schema.
-     */
-    protected function getTables()
+    protected function getTables(): array
     {
         if (is_null($this->tables)) {
-            $this->tables = collect($this->getSchema()->listTableNames())->all();
+            $this->tables = Schema::getTableListing(schema: config('database.connections.mariadb.database'), schemaQualified: false);
         }
 
         return $this->tables;
     }
 
-    /**
-     * Get the database schema for DB interactions.
-     */
-    protected function getSchema()
-    {
-        if (is_null($this->schema)) {
-            $this->schema = \DB::connection()->getDoctrineSchemaManager();
-        }
-
-        return $this->schema;
-    }
-
     protected function getTable(string $table_name)
     {
         return $this->getSchema()->introspectTable($table_name);
     }
 
+    /*
+     * returns array of columns in the form of:
+     *
+    [
+        "name" => "column_type"
+    "type_name" => "bigint"
+    "type" => "bigint(20) unsigned"
+    "collation" => null
+    "nullable" => true
+    "default" => "NULL"
+    "auto_increment" => false
+    "comment" => null
+    "generation" => null
+    ]
+    */
+    protected static function getTableColumns(string $table_name)
+    {
+        return Schema::getColumns($table_name);
+    }
+
+    /*
+     * returns array of foreign keys in the form of:
+     *
+     [
+        "name" => "foreign_key_name"
+        "columns" => [
+            0 => "local_column_name"
+        ]
+        "foreign_schema" => "schema_name"
+        "foreign_table" => "foreign_table_name"
+        "foreign_columns" => [
+            0 => "foreign_column_name"
+        ]
+        "on_update" => "restrict"
+        "on_delete" => "restrict"
+     ]
+     *
+     */
+    protected static function getTableForeignKeys(string $table_name)
+    {
+        return Schema::getForeignKeys($table_name);
+    }
+
     protected function getCurrentTable()
     {
         return $this->currentTable;
     }
 
-    protected function setCurrentTable(string $table_name)
+    protected function setCurrentTable(string $table_name): void
     {
-        $table = null;
-        if (!is_null($table_name) && '' !== trim($table_name)) {
-            $table = $this->getTable($table_name);
-        }
-        $this->currentTable = $table;
+        $this->currentTable = $table_name;
+    }
+
+    protected function format_file(string $path): void
+    {
+        exec('./vendor/bin/pint '.escapeshellarg($path));
     }
 
-    protected function format_file(string $path)
+    protected function getSnippet($snippet_name)
     {
-        exec('php-cs-fixer fix '.$path);
+        // Cache snippet contents to avoid re-reading files
+        if (! isset(self::$cached_snippets[$snippet_name])) {
+            self::$cached_snippets[$snippet_name] = $this->files->get(
+                $this->resolveStubPath("/snippets/$snippet_name.stub"));
+        }
+
+        return self::$cached_snippets[$snippet_name];
     }
 }
--- a/src/Generator/Controller/ControllerGenerator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Controller/ControllerGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,9 +1,9 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Controller;
+namespace Wizard\MagicForger\Generator\Controller;
 
 use Symfony\Component\Console\Attribute\AsCommand;
-use Wizzard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Generator\BaseGenerator;
 
 #[AsCommand(name: 'mf:controller')]
 class ControllerGenerator extends BaseGenerator
@@ -32,47 +32,46 @@
     /**
      * Execute the console command.
      */
-    public function handle()
+    public function handle(): void
     {
         parent::handle();
     }
 
     /**
      * Get the stub file for the generator.
-     *
-     * @return string
      */
-    protected function getStub()
+    protected function getStub(): string
     {
         return $this->resolveStubPath('/stubs/controller.stub');
     }
 
     /**
      * Resolve the fully-qualified path to the stub.
-     *
-     * @param string $stub
-     *
-     * @return string
      */
-    protected function resolveStubPath($stub)
+    protected function resolveStubPath(string $stub): string
     {
-        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
-            ? $customPath
-            : __DIR__.$stub;
+        $customPath = $this->laravel->basePath(trim($stub, '/'));
+
+        return is_file($customPath) ? $customPath : __DIR__.$stub;
     }
 
-    protected function getClassName($name)
+    /**
+     * Get the path for the generated file.
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(
+            ['App\\', '\\'],
+            ['app/', '/'],
+            $this->getControllerNamespace().'/'.$this->controller_name($this->getTableInput()).'.php'
+        );
+    }
+
+    /**
+     * Get the class name for the controller.
+     */
+    protected function getClassName(string $name): string
     {
         return $this->controller_name($name);
     }
-
-    /**
-     * Get the stub file for the generator.
-     *
-     * @return string
-     */
-    protected function getPath($name = null)
-    {
-        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getControllerNamespace().'/'.$this->controller_name($this->getTableInput()).'.php');
-    }
 }
--- a/src/Generator/Controller/stubs/controller.stub	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Controller/stubs/controller.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -10,91 +10,126 @@
 {
     /**
      * Display a listing of the resource.
+     *
+     * @param {{ filterRequest }} $request
+     * @return \Illuminate\View\View
      */
-    public function index()
+    public function index({{ filterRequest }} $request)
     {
-				$data = [];
-				
-				$data['items'] = {{ model }}::all();
+				$validated = $request->validated();
+        $data = [];
+        $data['items'] = {{ model }}::get_data($validated);
+				$data = array_merge($data, {{ model }}::load_index());
 
         return view('{{ tableName }}.index', $data);
     }
 
+    public function get_data()
+    {
+        $data = [];
+        $data['records'] = {{ model }}::get_data([]);
+        $data['total_records'] = count($data['records']);
+
+        return $data;
+    }
+
     /**
      * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\View\View
      */
     public function create()
     {
-				$data = []; 
+        $data = [];
+				$data = array_merge($data, {{ model }}::load_create());
 
         return view('{{ tableName }}.create_edit', $data);
     }
 
     /**
      * Store a newly created resource in storage.
+     *
+     * @param {{ storeRequest }} $request
+     * @return \Illuminate\Http\RedirectResponse
      */
     public function store({{ storeRequest }} $request)
     {
-				$validated = $request->validated();
-
-        //
-				${{ modelVariable }} = new {{ model }}();
+        $validated = $request->validated();
 
-				//insert the values into the model
-				// {{ valuesForCreation }}
-
-				${{ modelVariable }}->save();
+        {{ model }}::create($validated);
 
         return redirect()->route('{{ tableName }}.index');
     }
 
     /**
      * Display the specified resource.
+     *
+     * @param {{ model }} ${{ modelVariable }}
+     * @return \Illuminate\View\View
      */
     public function show({{ model }} ${{ modelVariable }})
     {
-				$data = [];
-				
-				$data['item'] = ${{ modelVariable }};
+        $data = [];
+        $data['item'] = ${{ modelVariable }};
+				$data['fields'] = (new {{ model }}())->getFillable();
+
+        return view('{{ tableName }}.show', $data);
+    }
 
-				return view('{{ tableName }}.show', $data); 
+		/**
+		 * Returns the resource in JSON format.
+		 *
+		 * @param ModelType $modelVariable
+		 * @return string
+		 */
+    public function load({{ model }} ${{ modelVariable }})
+    {
+        return ${{ modelVariable }}->toJson();
     }
 
     /**
      * Show the form for editing the specified resource.
+     *
+     * @param {{ model }} ${{ modelVariable }}
+     * @return \Illuminate\View\View
      */
     public function edit({{ model }} ${{ modelVariable }})
     {
-			$data = [];
+        $data = [];
+        $data['item'] = ${{ modelVariable }};
 
-			$data['item'] = ${{ modelVariable }};
+        // Load data for relationships
+				$data = array_merge($data, {{ model }}::load_edit());
 
-			return view('{{ tableName }}.create_edit', $data);
+        return view('{{ tableName }}.create_edit', $data);
     }
 
     /**
      * Update the specified resource in storage.
+     *
+     * @param {{ updateRequest }} $request
+     * @param {{ model }} ${{ modelVariable }}
+     * @return \Illuminate\Http\RedirectResponse
      */
     public function update({{ updateRequest }} $request, {{ model }} ${{ modelVariable }})
     {
-				$validated = $request->validated();
+        $validated = $request->validated();
 
-        // Set the variables
-				//{{ valuesForCreation }}
+        ${{ modelVariable }}->update($validated);
 
-				${{ modelVariable }}->save();
-
-				return redirect()->route('{{ tableName }}.index');
+        return redirect()->route('{{ tableName }}.index');
     }
 
     /**
      * Remove the specified resource from storage.
+     *
+     * @param {{ model }} ${{ modelVariable }}
+     * @return \Illuminate\Http\RedirectResponse
      */
     public function destroy({{ model }} ${{ modelVariable }})
     {
-        //
-				${{ modelVariable }}->delete();
+        ${{ modelVariable }}->delete();
 
-				return redirect()->route('{{ tableName }}.index');
+        return redirect()->route('{{ tableName }}.index');
     }
 }
--- a/src/Generator/Generator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Generator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,6 +1,6 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator;
+namespace Wizard\MagicForger\Generator;
 
 use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Input\InputInterface;
@@ -29,8 +29,9 @@
      */
     public function handle()
     {
+
         // First we need to ensure that the table exists, then we can
-        if (!$this->tableExists($this->getTableInput())) {
+        if (! $this->tableExists($this->getTableInput())) {
             $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
 
             return false;
@@ -46,6 +47,7 @@
             $this->input->setOption('controller', true);
             $this->input->setOption('model', true);
             $this->input->setOption('request', true);
+            $this->input->setOption('view', true);
             $this->input->setOption('route', true);
         }
 
@@ -73,6 +75,10 @@
             $this->createRequest();
         }
 
+        if ($this->option('view')) {
+            $this->createView();
+        }
+
         if ($this->option('route')) {
             $this->createRoute();
         }
@@ -80,34 +86,27 @@
 
     /**
      * Get the console command options.
-     *
-     * @return array
      */
-    protected function getOptions()
+    protected function getOptions(): array
     {
         return array_merge(parent::getOptions(), [
             ['all', 'a', InputOption::VALUE_NONE, 'Generate a migration, seeder, factory, policy, resource controller, and form request classes for the table.'],
             ['controller', 'c', InputOption::VALUE_NONE, 'Generate a controller class for the table.'],
             ['model', 'm', InputOption::VALUE_NONE, 'Generate a model class for the table.'],
             ['request', 'r', InputOption::VALUE_NONE, 'Generate base request classes for the table.'],
+            ['view', '', InputOption::VALUE_NONE, 'Generate base views for the table.'],
             ['route', 'w', InputOption::VALUE_NONE, 'Generate base routes classes for the table.'],
         ]);
     }
 
     /**
      * Interact further with the user if they were prompted for missing arguments.
-     *
-     * @return void
      */
-    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output)
-    {
-    }
+    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void {}
 
-    protected function getStub()
-    {
-    }
+    protected function getStub(): void {}
 
-    protected function createController()
+    protected function createController(): void
     {
         $this->call('mf:controller', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
     }
@@ -122,6 +121,11 @@
         $this->call('mf:request', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh'), '--all' => true]);
     }
 
+    protected function createView()
+    {
+        $this->call('mf:view', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh'), '--all' => true]);
+    }
+
     protected function createRoute()
     {
         $this->call('mf:route', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
--- a/src/Generator/Model/ModelGenerator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Model/ModelGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,9 +1,11 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Model;
+namespace Wizard\MagicForger\Generator\Model;
 
 use Symfony\Component\Console\Attribute\AsCommand;
-use Wizzard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Helpers\RelationshipNavigator;
+use Illuminate\Support\Str;
 
 #[AsCommand(name: 'mf:model')]
 class ModelGenerator extends BaseGenerator
@@ -29,12 +31,17 @@
      */
     protected $type = 'Model';
 
+    protected static $cached_snippets = [];
+
     /**
      * Execute the console command.
+     *
+     * @return mixed
      */
     public function handle()
     {
-        parent::handle();
+        // Delegate to parent handler (includes replacements and insertions)
+        return parent::handle();
     }
 
     /**
@@ -44,14 +51,17 @@
      */
     protected function getStub()
     {
+        if (! is_null(RelationshipNavigator::isPivot($this->getCurrentTable()))) {
+            return $this->resolveStubPath('/stubs/model.pivot.stub');
+        }
+
         return $this->resolveStubPath('/stubs/model.stub');
     }
 
     /**
      * Resolve the fully-qualified path to the stub.
      *
-     * @param string $stub
-     *
+     * @param  string  $stub
      * @return string
      */
     protected function resolveStubPath($stub)
@@ -75,4 +85,151 @@
     {
         return str_replace(['App\\', '\\'], ['app/', '/'], $this->getModelNamespace().'/'.$this->model_name($this->getTableInput()).'.php');
     }
+
+		protected function gatherRelations() {
+			$relations = RelationshipNavigator::getRelations($this->getCurrentTable());
+
+			return $relations;
+			
+		}
+
+		protected function renderFilters() {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            if (in_array($column['name'], $this->columns_to_ignore)) {
+                continue;
+            }
+						$snippet = $this->getSnippet('filter');
+						$tableName = $this->getCurrentTable();
+						$value = 'value'; // TODO: this should be determined based on column type
+						$columnName = $column['name'];
+						$columnDisplay = Str::headline($columnName);
+
+						// Replace placeholders with actual values
+        		$string = str_replace(
+        		    ['{{value}}', '{{columnDisplay}}', '{{tableName}}', '{{columnName}}'],
+        		    [$value, $columnDisplay, $tableName, $columnName],
+        		    $snippet
+        		);
+            $insert .= sprintf("%s", $string);
+        }
+
+				return $insert;
+		}
+
+		protected function renderRelations($relations) {
+			$renders = [
+				'belongsTo' => [],
+				'hasMany' => [],
+				'belongsToMany' => [],
+			];
+        // Render belongsTo relations
+        foreach (($relations['belongsTo'] ?? []) as $relation) {
+            $renders['belongsTo'][] = $this->renderBelongsTo($relation);
+        }
+
+        // Render hasMany relations
+        foreach (($relations['hasMany'] ?? []) as $relation) {
+            $renders['hasMany'][] = $this->renderHasMany($relation);
+        }
+
+			// Render belongsToMany (many-to-many) via hasManyThrough pivot relations
+			foreach (($relations['hasManyThrough'] ?? []) as $relation) {
+				$renders['belongsToMany'][] = $this->renderBelongsToMany($relation);
+			}
+			return $renders;
+		}
+
+    protected function renderBelongsTo($relationship)
+    {
+        $snippet = $this->getSnippet('belongs_to_relation');
+        $relationName = Str::singular($relationship['table']);
+        $relatedModel = $this->getClassName($relationship['table']);
+        $columnName = $relationship['column'];
+
+        // Replace placeholders with actual values
+        $string = str_replace(
+            ['{{relationName}}', '{{relatedModel}}', '{{columnName}}'],
+            [$relationName, $relatedModel, $columnName],
+            $snippet
+        );
+
+        return $string;
+    }
+
+    /**
+     * Render a hasMany relation.
+     *
+     * @param array $relationship
+     * @return string
+     */
+    protected function renderHasMany($relationship)
+    {
+        $snippet = $this->getSnippet('has_many_relation');
+        // Method name uses camel case for plural relation
+        $relationName = Str::camel($relationship['table']);
+        $relatedModel = $this->getClassName($relationship['table']);
+        $columnName = $relationship['column'];
+
+        // Replace placeholders with actual values
+        $string = str_replace(
+            ['{{relationName}}', '{{relatedModel}}', '{{columnName}}'],
+            [$relationName, $relatedModel, $columnName],
+            $snippet
+        );
+
+        return $string;
+    }
+
+    protected function renderBelongsToMany($relationship)
+    {
+        $snippet = $this->getSnippet('belongs_to_many_relation');
+        $relationName = $relationship['table'];
+        $relatedModel = $this->getClassName($relationship['table']);
+        $pivotTable = $relationship['through']['table'];
+        $foreignPivotKey = $relationship['through']['external_column'];
+        $relatedPivotKey = $relationship['through']['internal_column'];
+
+        // Replace placeholders with actual values
+        $string = str_replace(
+            ['{{relationName}}', '{{relatedModel}}', '{{pivotTable}}', '{{foreignPivotKey}}', '{{relatedPivotKey}}'],
+            [$relationName, $relatedModel, $pivotTable, $foreignPivotKey, $relatedPivotKey],
+            $snippet
+        );
+
+        return $string;
+    }
+
+    /**
+     * Get available insertions including model relationships.
+     *
+     * @return array
+     */
+    public function get_available_inserts(): array
+    {
+        // Merge parent insertions (attributes, fillable, etc.)
+        $inserts = parent::get_available_inserts();
+
+        // Gather and render relationships for this model
+        $relations = $this->gatherRelations();
+        $rendered = $this->renderRelations($relations);
+				$filters = $this->renderFilters();
+
+        // Build code blocks for each relation type
+        $belongs = !empty($rendered['belongsTo']) ? implode("\n    ", $rendered['belongsTo']) : '';
+        $hasMany = !empty($rendered['hasMany']) ? implode("\n    ", $rendered['hasMany']) : '';
+        $belongsMany = !empty($rendered['belongsToMany']) ? implode("\n    ", $rendered['belongsToMany']) : '';
+
+				// Default relations are based on the belongsTo relationship
+				$default_relations = implode(", \n",  array_map(function ($rel) {return '\'' . Str::singular($rel['table']) . '\''; }, $relations['belongsTo']));
+
+        // Assign to stub placeholders
+        $inserts['# {{ belongs_to_relationships }}'] = $belongs;
+        $inserts['# {{ has_many_relationships }}'] = $hasMany;
+        $inserts['# {{ has_many_through_relationships }}'] = $belongsMany;
+				$inserts['# {{ defaultRelationsInsertPoint }}'] = $default_relations;
+				$inserts['# {{ defaultFiltersInsertPoint }}'] = $filters;
+
+        return $inserts;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Model/snippets/belongs_to_many_relation.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,6 @@
+
+public function {{relationName}}()
+{
+    return $this->belongsToMany({{relatedModel}}::class, '{{pivotTable}}', '{{foreignPivotKey}}', '{{relatedPivotKey}}');
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Model/snippets/belongs_to_relation.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,6 @@
+
+public function {{relationName}}()
+{
+	return $this->belongsTo({{relatedModel}}::class, '{{columnName}}');
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Model/snippets/filter.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,6 @@
+'{{columnName}}' => [
+	'column_name' => '{{columnName}}',
+	'table' => '{{tableName}}',
+	'display' => '{{columnDisplay}}',
+	'type' => '{{value}}',
+],
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Model/snippets/has_many_relation.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,4 @@
+public function {{relationName}}()
+{
+    return $this->hasMany({{relatedModel}}::class, '{{columnName}}');
+}
--- a/src/Generator/Model/stubs/model.pivot.stub	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Model/stubs/model.pivot.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -10,12 +10,96 @@
 
     /**
      * Indicates if the model should be timestamped.
-		 * By default our pivots will not use timestamps
+     * By default our pivots will not use timestamps
      *
      * @var bool
      */
     public $timestamps = false;
 
+		protected $default_relations = [
+			# {{ defaultRelationsInsertPoint }}
+		];
 
 
+		//relations
+
+		// BelongsTo
+		# {{ belongs_to_relationships }}
+
+		// HasMany
+		# {{ has_many_relationships }}
+		
+    // HasManyThrough
+		# {{ has_many_through_relationships }}
+
+		/**
+		 * Load the default relations for the model.
+		 *
+		 * @return $this
+		 */
+		public function load_relations() {
+			foreach($this->default_relations as $relation) {
+				$this->load($relation);
+			}
+			return $this;
+		}
+
+		//MARK FOR MODEL
+		protected static function load_auxilary_data() {
+			$data = [];
+
+			$instance = new static();
+		
+		  foreach($instance->default_relations as $relation) {
+				$related_model = $instance->$relation()->getRelated();
+				$related_table = $related_model->getTable();
+				$data[$related_table] = $related_model->all()->pluck('name','id')->toArray();
+			}
+
+			return $data;
+		}
+
+		//MARK FOR MODEL
+		public static function load_index() {
+			return static::load_auxilary_data();
+		}
+
+		//MARK FOR MODEL
+		public static function load_create() {
+			return static::load_auxilary_data();
+		}
+
+		//MARK FOR MODEL
+		public static function load_edit() {
+			return static::load_auxilary_data();
+		}
+
+
+		/**
+		 * Retrieve a query builder instance with default relations loaded.
+		 *
+		 * @return \Illuminate\Database\Eloquent\Builder
+		 */
+		//MARK FOR MODEL
+		public static function data_query() {
+		    $query = static::query();
+		
+				$instance = new static();
+
+		    foreach($instance->default_relations as $relation) {
+		        $query->with($relation);
+		    }
+		
+		    return $query;
+		}
+
+		/**
+     * Retrieve a query builder instance with default relations loaded.
+     *
+     * @return \Illuminate\Database\Eloquent\Builder
+     */
+    public static function get_data()
+    {
+        return static::data_query()->get();
+    }
 }
--- a/src/Generator/Model/stubs/model.stub	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Model/stubs/model.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -2,11 +2,10 @@
 
 namespace {{ namespace }};
 
-use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\SoftDeletes;
+use Wizard\Framework\Models\BaseModel;
 
-class {{ class }} extends Model
+class {{ class }} extends BaseModel
 {
     //use HasFactory;
     use SoftDeletes;
@@ -27,17 +26,67 @@
 			# {{ atributeInsertPoint }}
     ];
 
+		protected $casts = [
+			# {{ castInsertPoint }}
+		];
 
-		public static function boot() : void {
-			parent::boot();
+		protected $fillable = [
+			# {{ fillableInsertPoint }}
+		];
+
+		protected $default_relations = [
+			# {{ defaultRelationsInsertPoint }}
+		];
+
+		protected static $filters = [
+			# {{ defaultFiltersInsertPoint }}
+		];
+
+		public static function get_filters() {
+			return static::filters;
+		}
+
+		//relations
+
+		// BelongsTo
+		# {{ belongs_to_relationships }}
+
+		// HasMany
+		# {{ has_many_relationships }}
+		
+    // HasManyThrough
+		# {{ has_many_through_relationships }}
+
 
-			self::creating(function ($item) {
-				$item->created_by = \Auth::user()->id;
-				$item->updated_by = \Auth::user()->id;
-			});
+		/**
+		 * Load the default relations for the model.
+		 *
+		 * @return $this
+		 */
+		public function load_relations() {
+			foreach($this->default_relations as $relation) {
+				$this->load($relation);
+			}
+			return $this;
+		}
 
-			self::saving(function ($item) {
-				$item->updated_by = \Auth::user()->id;
-			});
+		/**
+		 * Retrieve a query builder instance with default relations loaded.
+		 *
+		 * @return \Illuminate\Database\Eloquent\Builder
+		 */
+		public static function data_query() {
+			return parent::data_query();
 		}
+
+		/**
+     * Retrieve a query builder instance with default relations loaded.
+     *
+     * @return \Illuminate\Database\Eloquent\Builder
+     */
+    public static function get_data(array $validated = [])
+    {
+        return parent::get_data($validated);
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Requests/FilterRequestGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,77 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\Requests;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:filter_request')]
+class FilterRequestGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:filter_request';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the FilterRequest File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'FilterRequest';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/request.stub');
+    }
+
+    /**
+     * Resolve the fully-qualified path to the stub.
+     *
+     * @param  string  $stub
+     * @return string
+     */
+    protected function resolveStubPath($stub)
+    {
+        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
+            ? $customPath
+            : __DIR__.$stub;
+    }
+
+    protected function getClassName($name)
+    {
+        return $this->filter_request_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['App\\', '\\'], ['app/', '/'], $this->getRequestNamespace($this->getTableInput()).'/'.$this->filter_request_name($this->getTableInput()).'.php');
+    }
+}
--- a/src/Generator/Requests/RequestGenerator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Requests/RequestGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,12 +1,12 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Requests;
+namespace Wizard\MagicForger\Generator\Requests;
 
 use Symfony\Component\Console\Attribute\AsCommand;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
 use Symfony\Component\Console\Output\OutputInterface;
-use Wizzard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Generator\BaseGenerator;
 
 #[AsCommand(name: 'mf:request')]
 class RequestGenerator extends BaseGenerator
@@ -38,17 +38,22 @@
     public function handle()
     {
         // First we need to ensure that the table exists, then we can
-        if (!$this->tableExists($this->getTableInput())) {
+        if (! $this->tableExists($this->getTableInput())) {
             $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
 
             return false;
         }
 
         if ($this->option('all')) {
+            $this->input->setOption('filter_request', true);
             $this->input->setOption('store_request', true);
             $this->input->setOption('update_request', true);
         }
 
+        if ($this->option('filter_request')) {
+            $this->createFilterRequest();
+        }
+
         if ($this->option('store_request')) {
             $this->createStoreRequest();
         }
@@ -60,13 +65,12 @@
 
     /**
      * Get the console command options.
-     *
-     * @return array
      */
-    protected function getOptions()
+    protected function getOptions(): array
     {
         return array_merge(parent::getOptions(), [
             ['all', 'a', InputOption::VALUE_NONE, 'Generate all request classes for the table.'],
+            ['filter_request', 'i', InputOption::VALUE_NONE, 'Generate filter request class for the table.'],
             ['store_request', 's', InputOption::VALUE_NONE, 'Generate store request class for the table.'],
             ['update_request', 'u', InputOption::VALUE_NONE, 'Generate update request class for the table.'],
         ]);
@@ -74,20 +78,19 @@
 
     /**
      * Interact further with the user if they were prompted for missing arguments.
-     *
-     * @return void
      */
-    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output)
-    {
-    }
+    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void {}
 
     /**
      * Get the stub file for the generator.
      *
      * @return string
      */
-    protected function getStub()
+    protected function getStub() {}
+
+    protected function createFilterRequest()
     {
+        $this->call('mf:filter_request', ['table' => $this->getTableInput()]);
     }
 
     protected function createStoreRequest()
--- a/src/Generator/Requests/StoreRequestGenerator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Requests/StoreRequestGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,9 +1,9 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Requests;
+namespace Wizard\MagicForger\Generator\Requests;
 
 use Symfony\Component\Console\Attribute\AsCommand;
-use Wizzard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Generator\BaseGenerator;
 
 #[AsCommand(name: 'mf:store_request')]
 class StoreRequestGenerator extends BaseGenerator
@@ -50,8 +50,7 @@
     /**
      * Resolve the fully-qualified path to the stub.
      *
-     * @param string $stub
-     *
+     * @param  string  $stub
      * @return string
      */
     protected function resolveStubPath($stub)
--- a/src/Generator/Requests/UpdateRequestGenerator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Requests/UpdateRequestGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,9 +1,9 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Requests;
+namespace Wizard\MagicForger\Generator\Requests;
 
 use Symfony\Component\Console\Attribute\AsCommand;
-use Wizzard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Generator\BaseGenerator;
 
 #[AsCommand(name: 'mf:update_request')]
 class UpdateRequestGenerator extends BaseGenerator
@@ -50,8 +50,7 @@
     /**
      * Resolve the fully-qualified path to the stub.
      *
-     * @param string $stub
-     *
+     * @param  string  $stub
      * @return string
      */
     protected function resolveStubPath($stub)
--- a/src/Generator/Requests/stubs/request.stub	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Requests/stubs/request.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -22,7 +22,7 @@
     public function rules(): array
     {
         return [
-            //
+            // {{ valuesForValidation }} 
         ];
     }
 }
--- a/src/Generator/Route/RouteGenerator.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Generator/Route/RouteGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,9 +1,9 @@
 <?php
 
-namespace Wizzard\MagicForger\Generator\Route;
+namespace Wizard\MagicForger\Generator\Route;
 
 use Symfony\Component\Console\Attribute\AsCommand;
-use Wizzard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Generator\BaseGenerator;
 
 #[AsCommand(name: 'mf:routes')]
 class RouteGenerator extends BaseGenerator
@@ -50,8 +50,7 @@
     /**
      * Resolve the fully-qualified path to the stub.
      *
-     * @param string $stub
-     *
+     * @param  string  $stub
      * @return string
      */
     protected function resolveStubPath($stub)
--- a/src/Generator/Route/stubs/route.stub	Sat Dec 02 10:20:32 2023 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-<?php
-Route::controller({{ controllerName }}::class)
-	->prefix('{{ tableName }}') 
-	->alias('{{ tableName }}.')
-	->group( function () {
-		Route::get('/', 'index')->name('index');
-		Route::get('/create', 'create')->name('create');
-		Route::get('/edit', 'edit')->name('edit');
-
-		Route::post('/store', 'store')->name('store');
-		Route::put('/udpate/{id}', 'update')->name('update');
-		Route::delete('/delete/{id}', 'delete')->name('delete');
-	});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/Route/stubs/routes.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,19 @@
+<?php
+use Illuminate\Support\Facades\Route;
+use \App\Http\Controllers\{{ controllerName }};
+Route::controller({{ controllerName }}::class)
+	->middleware(['web','auth'])
+	->prefix('{{ tableName }}') 
+	->as('{{ tableName }}.')
+	->group( function () {
+        Route::get('/', 'index')->name('index');
+        Route::post('/get_data', 'get_data')->name('get_data');
+		Route::get('/create', 'create')->name('create');
+		Route::get('/{{{ modelVariable }}}/edit', 'edit')->name('edit');
+		Route::get('/{{{ modelVariable }}}', 'show')->name('show');
+		Route::get('/{{{ modelVariable }}}/load', 'load')->name('load');
+
+		Route::post('/store', 'store')->name('store');
+		Route::put('/udpate/{{{ modelVariable }}}', 'update')->name('update');
+		Route::delete('/destroy/{{{ modelVariable }}}', 'destroy')->name('destroy');
+	});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/CreateEditViewGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,164 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Helpers\RelationshipNavigator;
+use Illuminate\Support\Str;
+
+#[AsCommand(name: 'mf:create_edit_view')]
+class CreateEditViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:create_edit_view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the CreateEditView File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'CreateEditView';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/create_edit.stub');
+    }
+
+    /**
+     * Resolve the fully-qualified path to the stub.
+     *
+     * @param  string  $stub
+     * @return string
+     */
+    protected function resolveStubPath($stub)
+    {
+        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
+            ? $customPath
+            : __DIR__.$stub;
+    }
+
+    protected function getClassName($name)
+    {
+        return $this->create_edit_view_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['Resources\\', '\\'], ['resources/', '/'], $this->getViewNamespace($this->getTableInput()).'create_edit.blade.php');
+    }
+
+		protected function renderColumns() {
+				$renders = [];
+
+				$columns = $this->getTableColumns($this->getCurrentTable());
+        $relations = RelationshipNavigator::getRelations($this->getCurrentTable());
+				//gether the select columns based on the relations
+				$selects = [];
+
+				foreach($relations['belongsTo'] as $relation) {
+					$selects[$relation['column']] = $relation['table'];
+				}
+
+				foreach($columns as $column) {
+					$name = $column['name'];
+					if(in_array($name, $this->columns_to_ignore)) continue;
+
+					$type = $column['type_name'];
+
+					$replacements = [
+						'{{fieldName}}' => $name,
+						'{{fieldLabel}}' => Str::headline($name),
+						'{{required}}' => $column['nullable'] ? 'false' : 'true',
+					];
+					$snippet = '';
+
+					//date
+					if(in_array($type, ['date', 'timestamp'])) {
+						$snippet = $this->getSnippet('input/date');	
+					}
+					//checkbox
+					elseif(in_array($type, ['tinyint']) && array_key_exists($name, $selects)) {
+						$snippet = $this->getSnippet('input/checkbox');	
+					}
+
+					//select
+					elseif(in_array($type, ['bigint']) && array_key_exists($name, $selects)) {
+						$snippet = $this->getSnippet('input/select');	
+						$replacements['{{fieldLabel}}'] = Str::headline(Str::singular($selects[$name]));
+						$replacements['{{options}}'] = '$'.$selects[$name];
+					}
+
+					//text area
+					elseif(in_array($type, ['text'])) {
+						$snippet = $this->getSnippet('input/textarea');	
+					}
+					else {
+						//varchar, bigint, float, etc
+						$snippet = $this->getSnippet('input/text');	
+					}
+
+
+					// Replace placeholders with actual values
+        	$renders[] = str_replace(
+							array_keys($replacements),
+							$replacements,
+        	    $snippet
+        	);
+				}
+			return $renders;
+		}
+
+		
+
+    /**
+     * Get available insertions including model relationships.
+     *
+     * @return array
+     */
+    public function get_available_inserts(): array
+    {
+        // Merge parent insertions (attributes, fillable, etc.)
+        $inserts = parent::get_available_inserts();
+
+        // Gather and render relationships for this model
+        $rendered = $this->renderColumns();
+
+        // Build code blocks for each relation type
+        $columns = !empty($rendered) ? implode("\n    ", $rendered) : '';
+
+        // Assign to stub placeholders
+        $inserts['{{ fieldsInsertPoint }}'] = $columns;
+
+        return $inserts;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/IndexViewGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,173 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Illuminate\Support\Str;
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizard\MagicForger\Generator\BaseGenerator;
+use Wizard\MagicForger\Helpers\RelationshipNavigator;
+
+#[AsCommand(name: 'mf:index_view')]
+class IndexViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:index_view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the IndexView File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'IndexView';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/index.stub');
+    }
+
+    /**
+     * Resolve the fully-qualified path to the stub.
+     *
+     * @param  string  $stub
+     * @return string
+     */
+    protected function resolveStubPath($stub)
+    {
+        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
+            ? $customPath
+            : __DIR__.$stub;
+    }
+
+    protected function getClassName($name)
+    {
+        return $this->index_view_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['Resources\\', '\\'], ['resources/', '/'], $this->getViewNamespace($this->getTableInput()).'index.blade.php');
+    }
+
+    protected function renderColumns()
+    {
+        $renders = [];
+        $values = [];
+
+        $columns = $this->getTableColumns($this->getCurrentTable());
+        $relations = RelationshipNavigator::getRelations($this->getCurrentTable());
+        // gether the select columns based on the relations
+        $selects = [];
+
+        foreach ($relations['belongsTo'] as $relation) {
+            $selects[$relation['column']] = $relation['table'];
+        }
+
+        foreach ($columns as $column) {
+            $name = $column['name'];
+            if (in_array($name, $this->columns_to_ignore)) {
+                continue;
+            }
+
+            // Get the expected header name
+            $replacements = [
+                '{{header}}' => Str::headline($name),
+                '{{column_name}}' => $name,
+                '{{valueClass}}' => 'p-2',
+            ];
+
+            $type = $column['type_name'];
+
+            // date
+            if (in_array($type, ['date'])) {
+                $replacements['{{value}}'] = '{{ $item->'.$name.'?->format(\'Y-m-d\') ?? "" }}';
+            }
+            // time
+            if (in_array($type, ['timestamp'])) {
+                $replacements['{{value}}'] = '{{ $item->'.$name.'?->format(\'Y-m-d H:i\') ?? "" }}';
+            }
+            // checkbox
+            if (in_array($type, ['tinyint'])) {
+                $replacements['{{valueClass}}'] .= ' text-center';
+                $replacements['{{value}}'] = '{{ $item->'.$name.' ?? "0" }}';
+            }
+            // select
+            elseif (in_array($type, ['bigint']) && array_key_exists($name, $selects)) {
+                $replacements['{{header}}'] = Str::headline(Str::singular($selects[$name]));
+                $replacements['{{value}}'] = '{{ $item->'.Str::singular($selects[$name]).'?->name ?? "" }}';
+            }
+            // bigint, float
+            elseif (in_array($type, ['bigint', 'float', 'int'])) {
+                $replacements['{{valueClass}}'] .= ' text-start';
+            } else {
+                // text area
+                // varchar, , etc
+            }
+
+            $snippet = $this->getSnippet('index/value');
+            // Replace placeholders with actual values
+            $values[] = str_replace(
+                array_keys($replacements),
+                $replacements,
+                $snippet
+            );
+
+        }
+
+        return ['values' => $values];
+    }
+
+    /**
+     * Get available insertions including model relationships.
+     */
+    public function get_available_inserts(): array
+    {
+        // Merge parent insertions (attributes, fillable, etc.)
+        $inserts = parent::get_available_inserts();
+
+        // Gather and render relationships for this model
+        $rendered = $this->renderColumns();
+
+        // Build code blocks for each relation type
+        $headers = '';
+        $values = '';
+        $colCount = '';
+
+        if (! empty($rendered)) {
+            $values = ! empty($rendered['values']) ? implode("\n    ", $rendered['values']) : '';
+        }
+
+        // Assign to stub placeholders
+        $inserts['{{ columnInsertPoint }}'] = $values;
+
+        return $inserts;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/ShowViewGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,77 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Wizard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:show_view')]
+class ShowViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:show_view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the ShowView File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'ShowView';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        parent::handle();
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub()
+    {
+        return $this->resolveStubPath('/stubs/show.stub');
+    }
+
+    /**
+     * Resolve the fully-qualified path to the stub.
+     *
+     * @param  string  $stub
+     * @return string
+     */
+    protected function resolveStubPath($stub)
+    {
+        return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
+            ? $customPath
+            : __DIR__.$stub;
+    }
+
+    protected function getClassName($name)
+    {
+        return $this->show_view_name($name);
+    }
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getPath($name = null)
+    {
+        return str_replace(['Resources\\', '\\'], ['resources/', '/'], $this->getViewNamespace($this->getTableInput()).'show.blade.php');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/ViewGenerator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,105 @@
+<?php
+
+namespace Wizard\MagicForger\Generator\View;
+
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Wizard\MagicForger\Generator\BaseGenerator;
+
+#[AsCommand(name: 'mf:view')]
+class ViewGenerator extends BaseGenerator
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $name = 'mf:view';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Generates the View File for a table.';
+
+    /**
+     * The type of class being generated.
+     *
+     * @var string
+     */
+    protected $type = 'View';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        // First we need to ensure that the table exists, then we can
+        if (! $this->tableExists($this->getTableInput())) {
+            $this->components->error('The table: "'.$this->getTableInput().'" does not exist in the database.');
+
+            return false;
+        }
+
+        if ($this->option('all')) {
+            $this->input->setOption('index_view', true);
+            $this->input->setOption('create_edit_view', true);
+            $this->input->setOption('show_view', true);
+        }
+
+        if ($this->option('index_view')) {
+            $this->createIndexView();
+        }
+
+        if ($this->option('create_edit_view')) {
+            $this->createCreateEditView();
+        }
+
+        if ($this->option('show_view')) {
+            $this->createShowView();
+        }
+    }
+
+    /**
+     * Get the console command options.
+     */
+    protected function getOptions(): array
+    {
+        return array_merge(parent::getOptions(), [
+            ['all', 'a', InputOption::VALUE_NONE, 'Generate all views for the table.'],
+            ['index_view', 'i', InputOption::VALUE_NONE, 'Generate index view for the table.'],
+            ['create_edit_view', 'c', InputOption::VALUE_NONE, 'Generate create_edit view for the table.'],
+            ['show_view', 's', InputOption::VALUE_NONE, 'Generate show view for the table.'],
+        ]);
+    }
+
+    /**
+     * Interact further with the user if they were prompted for missing arguments.
+     */
+    protected function afterPromptingForMissingArguments(InputInterface $input, OutputInterface $output): void {}
+
+    /**
+     * Get the stub file for the generator.
+     *
+     * @return string
+     */
+    protected function getStub() {}
+
+    protected function createIndexView()
+    {
+        $this->call('mf:index_view', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
+    }
+
+    protected function createCreateEditView()
+    {
+        $this->call('mf:create_edit_view', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
+    }
+
+    protected function createShowView()
+    {
+        $this->call('mf:show_view', ['table' => $this->getTableInput(), '--fresh' => $this->option('fresh')]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/snippets/index/header.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,1 @@
+<th scope="col" class="{{headerClass}}">{{header}}</th>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/snippets/index/value.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,5 @@
+{
+    name: '{{column_name}}',
+    label: '{{header}}',
+    class: '{{valueClass}}'
+},
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/snippets/input/checkbox.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,5 @@
+<x-form.checkbox
+	name="{{fieldName}}"
+	label="{{fieldLabel}}"
+	:checked="request('{{fieldName}}', $item?->{{fieldName}} ?? 'false')"
+></x-form.checkbox>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/snippets/input/date.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,6 @@
+<x-form.date
+	name="{{fieldName}}"
+	label="{{fieldLabel}}"
+	:value="request('{{fieldName}}', optional($item?->{{fieldName}} ?? null)->format('Y-m-d') ?? '')"
+	:required="{{required}}"
+></x-form.date>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/snippets/input/select.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,7 @@
+<x-form.select
+	name="{{fieldName}}"
+	label="{{fieldLabel}}"
+	:options="{{options}}"
+	:value="request('{{fieldName}}', $item?->{{fieldName}} ?? '')"
+	:required="{{required}}"
+></x-form.select>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/snippets/input/text.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,6 @@
+<x-form.text
+	name="{{fieldName}}"
+	label="{{fieldLabel}}"
+	:value="request('{{fieldName}}', $item?->{{fieldName}} ?? '')"
+	:required="{{required}}"
+></x-form.text>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/snippets/input/textarea.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,6 @@
+<x-form.textarea
+	name="{{fieldName}}"
+	label="{{fieldLabel}}"
+	:value="request('{{fieldName}}', $item?->{{fieldName}} ?? '')"
+	:required="{{required}}"
+></x-form.textarea>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/stubs/create_edit.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,30 @@
+<x-app-layout>
+    <x-slot name="header">
+        <h2 class="fw-semibold fs-4 text-dark">
+            {{ isset($item) ? 'Edit' : 'Create' }} {{ ucfirst('{{ modelVariable }}') }}
+        </h2>
+    </x-slot>
+
+    <div class="py-5">
+        <div class="container">
+            <div class="bg-white shadow-sm rounded p-4">
+                    <form method="POST" action="{{ isset($item) ? route('{{ tableName }}.update', $item) : route('{{ tableName }}.store') }}">
+										@csrf
+                    @if (isset($item))
+                        @method('PUT')
+                    @endif
+
+										{{ fieldsInsertPoint }}
+
+                    <div class="d-flex justify-content-end">
+                        <a href="{{ route('{{ tableName }}.index') }}"
+                            class="btn btn-secondary me-2">Back</a>
+                        <button type="submit" class="btn btn-primary">
+                            {{ isset($item) ? 'Update' : 'Create' }}
+                        </button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</x-app-layout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/stubs/index.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,83 @@
+<x-app-layout>
+    <x-slot name="header">
+        <h2 class="fw-semibold fs-4 text-dark">
+            All {{ Str::plural(ucfirst('{{ modelVariable }}')) }}
+        </h2>
+    </x-slot>
+
+    <div class="py-5">
+        <div class="container">
+            <div class="bg-white shadow-sm rounded p-4">
+            	<div class="d-flex align-items-center justify-content-between mb-3">
+            	    <a href="{{ route('{{ tableName }}.create') }}" class="btn btn-primary">
+            	        + New {{ ucfirst('{{ modelVariable }}') }}
+            	    </a>
+            	</div>
+                <div id="my-table"></div>
+            </div>
+        </div>
+    </div>
+
+    @include('includes.ServerTable')
+    @pushOnce('scripts')
+        <meta name="csrf-token" content="{{ csrf_token() }}">
+    @endpushOnce
+    <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            const el = document.getElementById('my-table');
+            if (el) {
+                new ServerTable(el, {
+                    endpoint: '/{{ tableName }}/get_data',
+                    columns: [
+            	        {{ columnInsertPoint }}
+                        {
+                            name: 'actions',
+                            label: ' ',
+                            render: function(row, col, i) {
+                                let actions = `
+                                    <div class="d-flex gap-2">
+                                        <a href="{{ route('{{ tableName }}.show', 'PLACEHOLDER') }}" class="text-primary">View</a>
+                                        <a href="{{ route('{{ tableName }}.edit', 'PLACEHOLDER') }}" class="text-warning">Edit</a>
+                                        <form action="{{ route('{{ tableName }}.destroy', 'PLACEHOLDER') }}" method="POST"
+                                            class="d-inline">
+                                            @csrf
+                                            @method('DELETE')
+                                            <button type="submit" class="btn btn-link text-danger p-0"
+                                                onclick="return confirm('Delete?')">Delete</button>
+                                        </form>
+                                    </div>
+                                    `;
+                                actions = actions.split('PLACEHOLDER').join(row.id);
+                                return actions;
+                            }
+                        }
+                    ],
+                    pageSize: 10,
+                    initialSort: [{
+                        col: 'created_at',
+                        dir: 'desc'
+                    }],
+                    headers: {
+                        'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute(
+                            'content')
+                    },
+                    skeleton: `
+            <div class="st-table-container">
+                <table class="table table-hover">
+                    <thead>
+                    </thead>
+                    <tbody>
+                        <!-- Data rows will go here -->
+                    </tbody>
+                </table>
+                <div class="st-controls">
+                    <span class="st-pagination"></span>
+                    <span class="st-status"></span>
+                </div>
+            </div>
+        `
+                });
+            }
+        });
+    </script>
+</x-app-layout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Generator/View/stubs/show.stub	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,26 @@
+<x-app-layout>
+    <x-slot name="header">
+        <h2 class="fw-semibold fs-4 text-dark">
+            {{ ucfirst('{{ modelVariable }}') }} Details
+        </h2>
+    </x-slot>
+
+    <div class="py-5">
+        <div class="container">
+            <div class="bg-white shadow-sm rounded p-4">
+                <div class="mb-3">
+                    @foreach($fields as $field)
+                        <div class="mb-2">
+                            <span class="fw-semibold">{{ ucfirst($field) }}:</span>
+                            <span class="ms-2">{{ $item->$field }}</span>
+                        </div>
+                    @endforeach
+                </div>
+                <div class="d-flex justify-content-end mt-4">
+                    <a href="{{ route('{{ tableName }}.edit', $item) }}" class="me-2 btn btn-warning text-white">Edit</a>
+                    <a href="{{ route('{{ tableName }}.index') }}" class="btn btn-secondary">Back</a>
+                </div>
+            </div>
+        </div>
+    </div>
+</x-app-layout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Helpers/FileModifier.php	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,73 @@
+<?php
+
+namespace Wizard\MagicForger\Helpers;
+
+/*
+ * FileModifier
+ *
+ * A class that handles all file modifications
+ *
+ * General flow:
+ * Provide a file, a point to insert, and a value to insert.
+ * Insert the data.
+ *
+ * Replacements will consume the insert point.
+ * Inserts will maintain the insert point.
+ *
+ * */
+class FileModifier
+{
+    private $contents;
+
+    public $file_path;
+
+    public function __construct($file_path)
+    {
+        $this->get_file_contents($file_path);
+        $this->file_path = $file_path;
+    }
+
+    public function get_file_contents($file_path): void
+    {
+        // TODO: there needs to be more/any error checking
+        $f = fopen($file_path, 'r');
+        $this->contents = fread($f, filesize($file_path));
+        fclose($f);
+    }
+
+    public function write_to_path($file_path = null): void
+    {
+        $file_path = $file_path ?? $this->file_path;
+
+        $f = fopen($file_path, 'w');
+        fwrite($f, $this->contents);
+        fclose($f);
+    }
+
+    /**
+     * Replaces the replacement point with the value in the current contents.
+     */
+    public function replace($value, $replacement_point): void
+    {
+        $this->contents = str_replace($replacement_point, $value, $this->contents);
+    }
+
+    /**
+     * Inserts the value above the insert point in the current contents.
+     */
+    public function insert($value, $insert_point): void
+    {
+        // seperate on new lines into an array
+        $file_arr = explode("\n", $this->contents);
+        $temp_arr = [];
+
+        foreach ($file_arr as $line) {
+            if (str_contains($line, $insert_point)) {
+                $temp_arr[] = $value;
+            }
+            $temp_arr[] = $line;
+        }
+
+        $this->contents = implode("\n", $temp_arr);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Helpers/RelationshipNavigator.php	Wed Sep 10 21:00:47 2025 -0400
@@ -0,0 +1,232 @@
+<?php
+
+namespace Wizard\MagicForger\Helpers;
+
+use Illuminate\Support\Facades\DB;
+
+/**
+ * Class RelationshipNavigator
+ *
+ * This class is responsible for navigating database table relationships, specifically 
+ * identifying and categorizing 'belongsTo', 'hasMany', and 'hasManyThrough' relationships.
+ */
+class RelationshipNavigator
+{
+    /**
+     * Handles the retrieval and display of table relationships.
+     *
+     * @return void
+     */
+    public static function handle()
+    {
+        $tables = DB::select('SHOW TABLES');
+        $tableNames = array_map(fn($table) => current((array) $table), $tables);
+
+        foreach ($tableNames as $table) {
+            echo "Table: $table \n";
+
+            $relations = self::getRelations($table);
+            echo "Relationships: \n";
+
+            foreach ($relations as $relation => $relatedTables) {
+                echo "$relation: \n";
+                foreach ($relatedTables as $relatedTable) {
+                    echo "\t";
+                    foreach ($relatedTable as $key => $value) {
+                        if (is_array($value)) {
+                            echo "\n\t\t" . implode("\n\t\t", array_map(fn($k, $v) => "$k: $v", array_keys($value), $value));
+                        } else {
+                            echo "$key: $value ";
+                        }
+                    }
+                    echo "\n";
+                }
+            }
+            echo "\n --- \n";
+        }
+    }
+
+    /**
+     * Retrieves relationships of a specific table.
+     *
+     * @param string $table The table name.
+     * @return array An array containing 'belongsTo', 'hasMany', and 'hasManyThrough' relations.
+     */
+    public static function getRelations($table)
+    {
+        $relations = [
+            'belongsTo' => [],
+            'hasMany' => [],
+            'hasManyThrough' => [],
+        ];
+
+        $foreignKeys = DB::select("SHOW KEYS FROM $table WHERE Key_name != 'PRIMARY'");
+        $referencedTables = self::getAllReferencedTables($table);
+
+        // Determine 'belongsTo' Relationships
+        foreach ($foreignKeys as $fk) {
+            $column = $fk->Column_name;
+
+            // Skip certain columns
+            if (in_array($column, ['created_by', 'updated_by'])) {
+                continue;
+            }
+
+            $referencedTable = $referencedTables[$column] ?? null;
+
+            if ($referencedTable) {
+                $relations['belongsTo'][] = ['column' => $column, 'table' => $referencedTable->REFERENCED_TABLE_NAME];
+            }
+        }
+
+        // Determine 'hasMany' Relationships
+        if ($reverseRelation = self::findReverseRelation($table)) {
+            foreach ($reverseRelation as $relatedTable) {
+                $relations['hasMany'][] = $relatedTable;
+            }
+        }
+
+        // Determine 'hasManyThrough' Relationships
+        if ($hasManyThroughRelations = self::findHasManyThroughRelations($table)) {
+            foreach ($hasManyThroughRelations as $relatedTable) {
+                $relations['hasManyThrough'][] = $relatedTable;
+            }
+        }
+
+        return $relations;
+    }
+
+    /**
+     * Retrieves all referenced tables for a given table.
+     *
+     * @param string $table The table name.
+     * @return array|null An associative array of referenced tables, keyed by column name.
+     */
+    public static function getAllReferencedTables($table)
+    {
+        $results = DB::select("
+            SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME 
+            FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
+            WHERE TABLE_SCHEMA = DATABASE() 
+            AND REFERENCED_TABLE_NAME IS NOT NULL
+            AND TABLE_NAME = ?
+        ", [$table]);
+
+        return self::re_key_array($results, 'COLUMN_NAME') ?: null;
+    }
+
+    /**
+     * Finds 'hasMany' inverse relationships for a given table.
+     *
+     * @param string $table The table name.
+     * @return array|null An array of related tables with column names.
+     */
+    public static function findReverseRelation($table)
+    {
+        $relations = DB::select("
+            SELECT TABLE_NAME, COLUMN_NAME
+            FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
+            WHERE TABLE_SCHEMA = DATABASE() 
+            AND REFERENCED_TABLE_NAME = ? 
+            AND REFERENCED_COLUMN_NAME = 'id'
+            AND COLUMN_NAME NOT IN ('created_by', 'updated_by')
+        ", [$table]);
+
+        return array_map(fn($rel) => ['table' => $rel->TABLE_NAME, 'column' => $rel->COLUMN_NAME], $relations) ?: null;
+    }
+    
+    /**
+     * Finds 'hasManyThrough' relationships for a given table.
+     *
+     * @param string $table The table name.
+     * @return array An array of 'hasManyThrough' relationships.
+     */
+    public static function findHasManyThroughRelations($table)
+    {
+        $relations = [];
+        $intermediaryTables = self::findReverseRelation($table);
+
+        if ($intermediaryTables !== null) {
+            foreach ($intermediaryTables as $intermediary) {
+                if ($isPivot = self::isPivot($intermediary['table'])) {
+                    $isPivot = current($isPivot);
+
+                    $potentialTables = array_keys($isPivot['tables']);
+                    $externalTable = $potentialTables[0] === $table ? $isPivot['tables'][$potentialTables[1]] : $isPivot['tables'][$potentialTables[0]];
+                    $internalTable = $potentialTables[0] === $table ? $isPivot['tables'][$potentialTables[0]] : $isPivot['tables'][$potentialTables[1]];
+
+                    $hasManyThrough = [
+                        'table' => $externalTable['table_name'],
+                        'through' => [
+                            'table' => $isPivot['table'],
+                            'external_column' => $externalTable['column'],
+                            'internal_column' => $internalTable['column'],
+                        ],
+                    ];
+                    $relations[] = $hasManyThrough;
+                }
+            }
+        }
+
+        return $relations;
+    }
+
+    /**
+     * Determines if a table is a pivot table.
+     *
+     * @param string $table The table name.
+     * @return array|null An array with pivot details or null if not a pivot.
+     */
+    public static function isPivot($table)
+    {
+        $relations = [];
+        $pivotTables = DB::select("
+            SELECT TABLE_NAME, TABLE_COMMENT
+            FROM INFORMATION_SCHEMA.TABLES 
+            WHERE TABLE_SCHEMA = DATABASE() 
+            AND TABLE_NAME = ?
+            AND TABLE_COMMENT != ''
+        ", [$table]);
+
+        if (!is_null($pivotTables) && count($pivotTables) > 0) {
+            $ref = current($pivotTables);
+            $pivots = json_decode(str_replace('PIVOT:', '', $ref->TABLE_COMMENT), true);
+            $tables = [];
+
+            if (count($pivots) > 0) {
+                $references = self::getAllReferencedTables($table);
+                $references = self::re_key_array($references, 'REFERENCED_TABLE_NAME');
+
+                foreach ($pivots as $key => $value) {
+                    if ($refData = ($references[$value] ?? null)) {
+                        $tables[$value] = [
+                            'table_name' => $value,
+                            'column' => $refData->COLUMN_NAME,
+                        ];
+                    }
+                }
+            }
+            $relations[] = ['table' => $ref->TABLE_NAME, 'tables' => $tables];
+        }
+
+        return !empty($relations) ? $relations : null;
+    }
+
+    /**
+     * Re-keys an array of objects using a specific object's property.
+     *
+     * @param array $oldArray The original array of objects.
+     * @param string $key The key to re-index by.
+     * @return array The re-keyed array.
+     */
+    public static function re_key_array($oldArray, $key)
+    {
+        $newArray = [];
+        if (count($oldArray) > 0) {
+            foreach ($oldArray as $array) {
+                $newArray[$array->$key] = $array;
+            }
+        }
+        return $newArray;
+    }
+}
--- a/src/MagicForgerServiceProvider.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/MagicForgerServiceProvider.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,15 +1,20 @@
 <?php
 
-namespace Wizzard\MagicForger;
+namespace Wizard\MagicForger;
 
 use Illuminate\Support\ServiceProvider;
-use Wizzard\MagicForger\Generator\Controller\ControllerGenerator;
-use Wizzard\MagicForger\Generator\Generator;
-use Wizzard\MagicForger\Generator\Model\ModelGenerator;
-use Wizzard\MagicForger\Generator\Requests\RequestGenerator;
-use Wizzard\MagicForger\Generator\Requests\StoreRequestGenerator;
-use Wizzard\MagicForger\Generator\Requests\UpdateRequestGenerator;
-use Wizzard\MagicForger\Generator\Route\RouteGenerator;
+use Wizard\MagicForger\Generator\Controller\ControllerGenerator;
+use Wizard\MagicForger\Generator\Generator;
+use Wizard\MagicForger\Generator\Model\ModelGenerator;
+use Wizard\MagicForger\Generator\Requests\RequestGenerator;
+use Wizard\MagicForger\Generator\Requests\FilterRequestGenerator;
+use Wizard\MagicForger\Generator\Requests\StoreRequestGenerator;
+use Wizard\MagicForger\Generator\Requests\UpdateRequestGenerator;
+use Wizard\MagicForger\Generator\Route\RouteGenerator;
+use Wizard\MagicForger\Generator\View\ViewGenerator;
+use Wizard\MagicForger\Generator\View\IndexViewGenerator;
+use Wizard\MagicForger\Generator\View\CreateEditViewGenerator;
+use Wizard\MagicForger\Generator\View\ShowViewGenerator;
 
 class MagicForgerServiceProvider extends ServiceProvider
 {
@@ -24,9 +29,14 @@
                 ControllerGenerator::class,
                 ModelGenerator::class,
                 RequestGenerator::class,
+                FilterRequestGenerator::class,
                 StoreRequestGenerator::class,
                 UpdateRequestGenerator::class,
                 RouteGenerator::class,
+                ViewGenerator::class,
+                IndexViewGenerator::class,
+                CreateEditViewGenerator::class,
+                ShowViewGenerator::class,
             ]);
         }
 
--- a/src/Replacer/Replacer.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Replacer/Replacer.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,6 +1,6 @@
 <?php
 
-namespace Wizzard\MagicForger\Replacer;
+namespace Wizard\MagicForger\Replacer;
 
 use Illuminate\Support\Str;
 
@@ -9,27 +9,22 @@
     /**
      * Prefix and Suffix for controller.
      * Usage is up to the user.
-     *
-     * @var string
      */
-    protected $controller_prefix = '';
+    protected string $controller_prefix = '';
 
     /**
      * Prefix and Suffix for controller.
      * Usage is up to the user.
-     *
-     * @var string
      */
-    protected $controller_suffix = 'Controller';
+    protected string $controller_suffix = 'Controller';
 
     /**
      * Finds all places in a string that could be replaced.
-     * Returns an array of all potential replacements as they
-     * appear in the target.
+     * Returns an array of all potential replacements as they appear in the target.
      */
     public function get_all_keywords(string $target): array
     {
-        // find all the matches to our expected syntax
+        // find all matches to our expected syntax
         $matches = [];
         preg_match_all('/{{[\sa-zA-Z\-_]+}}/', $target, $matches);
         // sort the array and return unique values
@@ -38,46 +33,48 @@
         return array_values(array_unique($matches[0]));
     }
 
+    /**
+     * Apply replacements to the target string.
+     */
     public function apply_replacements(string $target): string
     {
         $inserts = $this->get_all_keywords($target);
         $available_replacements = $this->get_available_replacements();
 
-        $target = str_replace(
+        return str_replace(
             array_keys($available_replacements),
             $available_replacements,
             $target
         );
-
-        return $target;
     }
 
-    public function get_available_replacements()
+    /**
+     * Get available replacements for string replacements.
+     */
+    public function get_available_replacements(): array
     {
         $table_name = $this->getTableInput();
-        $replacements = [
-                    '{{ class }}' => $this->getClassName($table_name),
-                    '{{ controllerName }}' => $this->controller_name($table_name),
-                    '{{ model }}' => $this->model_name($table_name),
-                    '{{ modelVariable }}' => $this->model_variable($table_name),
-                    '{{ namespace }}' => $this->{'get'.$this->type.'Namespace'}($table_name),
-                    '{{ namespacedModel }}' => $this->getNamespacedModel($table_name),
-                    '{{ requestUses }}' => $this->getRequestUses($table_name),
-                    '{{ rootNamespace }}' => $this->getRootNamespace(),
-                    '{{ storeRequest }}' => $this->store_request_name($table_name),
-                    '{{ tableName }}' => $table_name,
-                    '{{ updateRequest }}' => $this->update_request_name($table_name),
+
+        return [
+            '{{ class }}' => $this->getClassName($table_name),
+            '{{ controllerName }}' => $this->controller_name($table_name),
+            '{{ model }}' => $this->model_name($table_name),
+            '{{ modelVariable }}' => $this->model_variable($table_name),
+            '{{ namespace }}' => $this->{'get'.$this->type.'Namespace'}($table_name),
+            '{{ namespacedModel }}' => $this->getNamespacedModel($table_name),
+            '{{ requestUses }}' => $this->getRequestUses($table_name),
+            '{{ rootNamespace }}' => $this->getRootNamespace(),
+            '{{ storeRequest }}' => $this->store_request_name($table_name),
+            '{{ filterRequest }}' => $this->filter_request_name($table_name),
+            '{{ updateRequest }}' => $this->update_request_name($table_name),
+            '{{ tableName }}' => $table_name,
         ];
-
-        return $replacements;
     }
 
-    // //////////////////////////////////////////
-    //				Internals and Classes   				//
-    // //////////////////////////////////////////
+    // Model and Controller Naming
 
     /**
-     * Model names are generated in uppercase first Camel case.
+     * Generate model name in Studly case.
      */
     public function model_name(string $name): string
     {
@@ -85,17 +82,15 @@
     }
 
     /**
-     * Model variable is standardly just a singular version of the table name.
+     * Generate singular model variable name.
      */
     public function model_variable(string $name): string
     {
-        /* return Str::singular($name); */
-        return 'item';
+        return Str::singular($name);
     }
 
     /**
-     * Controller names are generated in uppercase first Camel case
-     * and wrapped in the prefix and suffix.
+     * Generate controller name using prefix/suffix and studly case.
      */
     public function controller_name(string $name): string
     {
@@ -104,76 +99,192 @@
             $this->controller_suffix;
     }
 
+    /**
+     * Generate the store request name.
+     */
     public function store_request_name(string $name): string
     {
         return 'Store'.$this->model_name($name).'Request';
     }
 
+    /**
+     * Generate the filter request name.
+     */
+    public function filter_request_name(string $name): string
+    {
+        return 'Filter'.$this->model_name($name).'Request';
+    }
+
+    /**
+     * Generate the update request name.
+     */
     public function update_request_name(string $name): string
     {
         return 'Update'.$this->model_name($name).'Request';
     }
 
-    // //////////////////////////////////////////
-    //							Namespaces			   				//
-    // //////////////////////////////////////////
+
+    /**
+     * Generate the index view name.
+     */
+    public function index_view_name(string $name): string
+    {
+        return '';
+    }
+
+    /**
+     * Generate the create_edit view name.
+     */
+    public function create_edit_view_name(string $name): string
+    {
+        return '';
+    }
 
-    public function getRootNamespace()
+    /**
+     * Generate the show view name.
+     */
+    public function show_view_name(string $name): string
+    {
+        return '';
+    }
+
+
+    /**
+     * Generate route name in Studly case.
+     */
+    public function routes_name(string $name): string
+    {
+        return Str::singular(Str::studly($name));
+    }
+
+    // Namespace Methods
+    // These methods handle the formation of various namespaces used within the replacements.
+
+    /**
+     * Get the root namespace for the application.
+     */
+    public function getRootNamespace(): string
     {
         return $this->laravel->getNamespace();
     }
 
-    public function getModelNamespace(string $name = '')
+    /**
+     * Get the model namespace.
+     */
+    public function getRouteNamespace(string $name = ''): string
+    {
+			return base_path()
+				. DIRECTORY_SEPARATOR . 'routes' 
+				. DIRECTORY_SEPARATOR . 'resources'
+				;
+    }
+
+    /**
+     * Get the model namespace.
+     */
+    public function getModelNamespace(string $name = ''): string
     {
         return $this->getRootNamespace().'Models';
     }
 
-    public function getNamespacedModel(string $name = '')
+    /**
+     * Get the fully-qualified namespaced model class.
+     */
+    public function getNamespacedModel(string $name = ''): string
     {
         return $this->getModelNamespace().'\\'.$this->model_name($name);
     }
 
-    public function getControllerNamespace(string $name = '')
+    /**
+     * Get the controller namespace.
+     */
+    public function getControllerNamespace(string $name = ''): string
     {
         return $this->getRootNamespace().'Http\\Controllers';
     }
 
-    public function getRequestNamespace(string $name)
+    /**
+     * Get the request namespace.
+     */
+    public function getRequestNamespace(string $name): string
     {
         return $this->getRootNamespace().'Http\\Requests\\'.$this->model_name($name);
     }
 
-    public function getStoreRequestNamespace(string $name)
+    /**
+     * Get the store request namespace.
+     */
+    public function getStoreRequestNamespace(string $name): string
     {
         return $this->getRequestNamespace($name);
     }
 
-    public function getUpdateRequestNamespace(string $name)
+    /**
+     * Get the filter request namespace.
+     */
+    public function getFilterRequestNamespace(string $name): string
+    {
+        return $this->getRequestNamespace($name);
+    }
+
+    /**
+     * Get the update request namespace.
+     */
+    public function getUpdateRequestNamespace(string $name): string
     {
         return $this->getRequestNamespace($name);
     }
 
-    public function getRequestUses(string $name)
+    /**
+     * Get the view namespace.
+     */
+    public function getViewNamespace(string $name): string
+    {
+        return $this->viewPath($name) . '\\';
+    }
+
+    /**
+     * Get the index view namespace.
+     */
+    public function getIndexViewNamespace(string $name): string
+    {
+        return $this->getViewNamespace($name) . '\\';
+    }
+
+    /**
+     * Get the create_edit view namespace.
+     */
+    public function getCreateEditViewNamespace(string $name): string
+    {
+        return $this->getViewNamespace($name) . '\\';
+    }
+
+    /**
+     * Get the show view namespace.
+     */
+    public function getShowViewNamespace(string $name): string
+    {
+        return $this->getViewNamespace($name) . '\\';
+    }
+
+
+    /**
+     * Get the request uses string for replacement.
+     */
+    public function getRequestUses(string $name): string
     {
         return implode("\n", [
             'use '.$this->getRequestNamespace($name).'\\'.$this->store_request_name($name).';',
+            'use '.$this->getRequestNamespace($name).'\\'.$this->filter_request_name($name).';',
             'use '.$this->getRequestNamespace($name).'\\'.$this->update_request_name($name).';',
         ]);
     }
 
-    public function getRouteNamespace(string $name = '')
-    {
-        return $this->getRootNamespace().'Http\\Controllers';
-    }
-
-    // //////////////////////////////////////////
-    //				Language and Presentables				//
-    // //////////////////////////////////////////
+    // Text Manipulation
 
     /**
-     * Breaks up a string and makes it human readable.
-     *
-     * This function assumes that the inputted name is camel case
+     * Convert a string to a human-readable format.
+     * Assumes camel case input.
      */
     public function human_readable(string $name): string
     {
@@ -181,9 +292,8 @@
     }
 
     /**
-     * Breaks up a string and makes it human readable and lowecase.
-     *
-     * This function assumes that the inputted name is camel case
+     * Convert a string to a lowercase human-readable format.
+     * Assumes camel case input.
      */
     public function human_readable_lc(string $name): string
     {
--- a/src/Replacer/TableReplacer.php	Sat Dec 02 10:20:32 2023 -0500
+++ b/src/Replacer/TableReplacer.php	Wed Sep 10 21:00:47 2025 -0400
@@ -1,59 +1,144 @@
 <?php
 
-namespace Wizzard\MagicForger\Replacer;
+namespace Wizard\MagicForger\Replacer;
 
 trait TableReplacer
 {
-    protected $columns;
+    protected ?array $columns = null;
 
-    protected function get_columns()
+    protected array $columns_to_ignore = [
+        'id',
+        'created_at',
+        'updated_at',
+        'created_by',
+        'updated_by',
+        'deleted_at',
+    ];
+
+    /**
+     * Retrieve columns for the current table.
+     */
+    protected function get_columns(): array
     {
         if (is_null($this->columns)) {
-            $this->columns = $this->getCurrentTable()->getColumns();
+            $this->columns = $this->getTableColumns($this->getCurrentTable());
         }
 
         return $this->columns;
     }
 
-    protected function get_attributes()
+    /**
+     * Get a string representation of values for creation.
+     */
+    protected function getValuesForCreation(): string
     {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            $column_name = $column['name'];
+            $insert .= sprintf('$item->%s = $validated["%s"] ?? NULL;', $column_name, $column_name)."\n";
+        }
+
+        return $insert;
     }
 
-    protected function getValuesForCreation()
+    /**
+     * Get a string representation of table attributes.
+     */
+    protected function getCasts(): string
     {
         $insert = '';
         foreach ($this->get_columns() as $column) {
-            $insert .= '$item->'.$column->getName().' = $validated["'.$column->getName().'"] ?? NULL;'."\n";
+            if (in_array($column['name'], $this->columns_to_ignore)) {
+                continue;
+            }
+						$type = $column['type_name'];
+						//date
+						if(in_array($type, ['date'])) {
+							$insert .= sprintf("'%s' => 'date:Y-m-d',", $column['name'])."\n";
+						}
+						//time
+						if(in_array($type, ['timestamp'])) {
+							$insert .= sprintf("'%s' => 'date:Y-m-d H:i',", $column['name'])."\n";
+						}
+        }
+
+        return $insert;
+    }
+
+    /**
+     * Get a string representation of table attributes.
+     */
+    protected function getAttributes(): string
+    {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            if (in_array($column['name'], $this->columns_to_ignore)) {
+                continue;
+            }
+            $insert .= sprintf("'%s' => '',", $column['name'])."\n";
         }
 
         return $insert;
     }
 
+    /**
+     * Get a string representation of table fillable columns.
+     */
+    protected function getFillable(): string
+    {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            if (in_array($column['name'], $this->columns_to_ignore)) {
+                continue;
+            }
+            $insert .= sprintf("'%s',", $column['name'])."\n";
+        }
+
+        return $insert;
+    }
+
+    /**
+     * Get formatted validation rules for table columns.
+     */
+    protected function getValuesForValidation(): string
+    {
+        $insert = '';
+        foreach ($this->get_columns() as $column) {
+            if (in_array($column['name'], $this->columns_to_ignore)) {
+                continue;
+            }
+            $insert .= sprintf("'%s' => 'nullable',", $column['name'])."\n";
+        }
+
+        return $insert;
+    }
+
+    /**
+     * Apply insertions in the target template.
+     */
     public function apply_inserts(string $target): string
     {
         $inserts = $this->get_all_keywords($target);
-        $available_replacements = $this->get_available_inserts();
+        $available_insertions = $this->get_available_inserts();
 
-        $target = str_replace(
-            array_keys($available_replacements),
-            $available_replacements,
+        return str_replace(
+            array_keys($available_insertions),
+            $available_insertions,
             $target
         );
-
-        return $target;
     }
 
-    public function get_available_inserts()
+    /**
+     * Get available insertion points for the template.
+     */
+    public function get_available_inserts(): array
     {
-        $table_name = $this->getTableInput();
-        $replacements = [
-                        '// {{ valuesForCreation }}' => self::getValuesForCreation(),
+        return [
+            '// {{ valuesForCreation }}' => $this->getValuesForCreation(),
+            '# {{ attributeInsertPoint }}' => $this->getAttributes(),
+            '# {{ castInsertPoint }}' => $this->getCasts(),
+            '# {{ fillableInsertPoint }}' => $this->getFillable(),
+            '// {{ valuesForValidation }}' => $this->getValuesForValidation(),
         ];
-
-        foreach ($replacements as $key => &$replacement) {
-            $replacement = $replacement."\n".$key;
-        }
-
-        return $replacements;
     }
 }