Skip to content

Commit 2e35e77

Browse files
committed
- Livewire layout updates using flux for Laravel12
- issue #52 - issue #56
1 parent d84cdc7 commit 2e35e77

24 files changed

+617
-257
lines changed

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
"laravel package",
1717
"bootstrap css",
1818
"tailwind css",
19-
"alpine js"
19+
"alpine js",
20+
"livewire"
2021
],
2122
"require": {
2223
"php": "^8.2",
23-
"laravel/framework": "^10.30|^11.0|^12.0"
24+
"laravel/framework": "^10.30|^11.44|^12.2"
2425
},
2526
"autoload": {
2627
"psr-4": {

composer.lock

Lines changed: 370 additions & 205 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Commands/CrudGenerator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,13 @@ protected function buildViews(): static
278278
$this->buildLayout();
279279

280280
foreach (['index', 'create', 'edit', 'form', 'show'] as $view) {
281+
$path = match ($this->options['stack']) {
282+
'livewire' => $this->isLaravel12() ? "views/{$this->options['stack']}/12/$view" : "views/{$this->options['stack']}/default/$view",
283+
default => "views/{$this->options['stack']}/$view"
284+
};
285+
281286
$viewTemplate = str_replace(
282-
array_keys($replace), array_values($replace), $this->getStub("views/{$this->options['stack']}/$view")
287+
array_keys($replace), array_values($replace), $this->getStub($path)
283288
);
284289

285290
$this->write($this->_getViewPath($view), $viewTemplate);

src/Commands/GeneratorCommand.php

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ public function __construct(Filesystem $files)
8888
$this->layout = config('crud.layout', $this->layout);
8989
}
9090

91+
/**
92+
* @return bool
93+
*/
94+
public function isLaravel12(): bool
95+
{
96+
return str_starts_with(app()->version(), '12');
97+
}
98+
9199
/**
92100
* Generate the controller.
93101
*
@@ -128,10 +136,10 @@ protected function makeDirectory(string $path): string
128136
/**
129137
* Write the file/Class.
130138
*
131-
* @param $path
132-
* @param $content
139+
* @param string $path
140+
* @param string $content
133141
*/
134-
protected function write($path, $content): void
142+
protected function write(string $path, string $content): void
135143
{
136144
$this->makeDirectory($path);
137145

@@ -175,73 +183,73 @@ private function _getSpace(int $no = 1): string
175183
}
176184

177185
/**
178-
* @param $name
186+
* @param string $name
179187
*
180188
* @return string
181189
*/
182-
protected function _getControllerPath($name): string
190+
protected function _getControllerPath(string $name): string
183191
{
184192
return app_path($this->_getNamespacePath($this->controllerNamespace)."{$name}Controller.php");
185193
}
186194

187195
/**
188-
* @param $name
196+
* @param string $name
189197
*
190198
* @return string
191199
*/
192-
protected function _getApiControllerPath($name): string
200+
protected function _getApiControllerPath(string $name): string
193201
{
194202
return app_path($this->_getNamespacePath($this->apiControllerNamespace)."{$name}Controller.php");
195203
}
196204

197205
/**
198-
* @param $name
206+
* @param string $name
199207
*
200208
* @return string
201209
*/
202-
protected function _getResourcePath($name): string
210+
protected function _getResourcePath(string $name): string
203211
{
204212
return app_path($this->_getNamespacePath($this->resourceNamespace)."{$name}Resource.php");
205213
}
206214

207215
/**
208-
* @param $name
216+
* @param string $name
209217
*
210218
* @return string
211219
*/
212-
protected function _getLivewirePath($name): string
220+
protected function _getLivewirePath(string $name): string
213221
{
214222
return app_path($this->_getNamespacePath($this->livewireNamespace)."{$name}.php");
215223
}
216224

217225
/**
218-
* @param $name
226+
* @param string $name
219227
*
220228
* @return string
221229
*/
222-
protected function _getRequestPath($name): string
230+
protected function _getRequestPath(string $name): string
223231
{
224232
return app_path($this->_getNamespacePath($this->requestNamespace)."{$name}Request.php");
225233
}
226234

227235
/**
228-
* @param $name
236+
* @param string $name
229237
*
230238
* @return string
231239
*/
232-
protected function _getModelPath($name): string
240+
protected function _getModelPath(string $name): string
233241
{
234242
return $this->makeDirectory(app_path($this->_getNamespacePath($this->modelNamespace)."$name.php"));
235243
}
236244

237245
/**
238246
* Get the path from namespace.
239247
*
240-
* @param $namespace
248+
* @param string $namespace
241249
*
242250
* @return string
243251
*/
244-
private function _getNamespacePath($namespace): string
252+
private function _getNamespacePath(string $namespace): string
245253
{
246254
$str = Str::start(Str::finish(Str::after($namespace, 'App'), '\\'), '\\');
247255

@@ -259,11 +267,11 @@ private function _getLayoutPath(): string
259267
}
260268

261269
/**
262-
* @param $view
270+
* @param string $view
263271
*
264272
* @return string
265273
*/
266-
protected function _getViewPath($view): string
274+
protected function _getViewPath(string $view): string
267275
{
268276
$name = Str::kebab($this->name);
269277
$path = match ($this->options['stack']) {
@@ -300,41 +308,45 @@ protected function buildReplacements(): array
300308
];
301309
}
302310

303-
protected function _getRoute()
311+
protected function _getRoute(): string
304312
{
305313
return $this->options['route'] ?? Str::kebab(Str::plural($this->name));
306314
}
307315

308316
/**
309317
* Build the form fields for form.
310318
*
311-
* @param $title
312-
* @param $column
319+
* @param string $title
320+
* @param string $column
313321
* @param string $type
314322
*
315323
* @return string
316324
* @throws FileNotFoundException
317-
*
318325
*/
319-
protected function getField($title, $column, string $type = 'form-field'): string
326+
protected function getField(string $title, string $column, string $type = 'form-field'): string
320327
{
321328
$replace = array_merge($this->buildReplacements(), [
322329
'{{title}}' => $title,
323330
'{{column}}' => $column,
324331
'{{column_snake}}' => Str::snake($column),
325332
]);
326333

334+
$path = match ($this->options['stack']) {
335+
'livewire' => $this->isLaravel12() ? "views/{$this->options['stack']}/12/$type" : "views/{$this->options['stack']}/default/$type",
336+
default => "views/{$this->options['stack']}/$type"
337+
};
338+
327339
return str_replace(
328-
array_keys($replace), array_values($replace), $this->getStub("views/{$this->options['stack']}/$type")
340+
array_keys($replace), array_values($replace), $this->getStub($path)
329341
);
330342
}
331343

332344
/**
333-
* @param $title
345+
* @param string $title
334346
*
335347
* @return string
336348
*/
337-
protected function getHead($title): string
349+
protected function getHead(string $title): string
338350
{
339351
$replace = array_merge($this->buildReplacements(), [
340352
'{{title}}' => $title,
@@ -382,18 +394,19 @@ protected function getBody($column): string
382394
*/
383395
protected function buildLayout(): void
384396
{
385-
if ($this->layout === false || $this->layout === null) {
397+
if ($this->layout === false) {
386398
return;
387399
}
388400

389-
if (view()->exists($this->layout)) {
401+
if (view()->exists($this->layout) || view()->exists('components.'.$this->layout)) {
390402
return;
391403
}
392404

393405
$this->info('Creating Layout ...');
394406

395407
$uiPackage = match ($this->options['stack']) {
396-
'tailwind', 'livewire', 'react', 'vue' => 'laravel/breeze',
408+
'tailwind', 'react', 'vue' => 'laravel/breeze',
409+
'livewire' => $this->isLaravel12() ? 'laravel/livewire-starter-kit' : 'laravel/breeze',
397410
default => 'laravel/ui'
398411
};
399412

@@ -409,6 +422,11 @@ protected function buildLayout(): void
409422
default => 'php artisan ui bootstrap --auth'
410423
};
411424

425+
// Do not run command for v12.*
426+
if ($this->isLaravel12()) {
427+
return;
428+
}
429+
412430
$this->runCommands([$uiCommand]);
413431
}
414432

src/ModelGenerator.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ public function __construct(string $table, string $properties, string $modelName
3636
*
3737
* @return array
3838
*/
39-
public function getEloquentRelations()
39+
public function getEloquentRelations(): array
4040
{
4141
return [$this->functions, $this->properties];
4242
}
4343

44-
private function _init()
44+
private function _init(): void
4545
{
4646
foreach ($this->_getTableRelations() as $relation) {
4747
$this->functions .= $this->_getFunction($relation);
4848
}
4949
}
5050

51-
private function _getFunction(array $relation)
51+
private function _getFunction(array $relation): string
5252
{
5353
switch ($relation['name']) {
5454
case 'hasOne':
@@ -76,7 +76,7 @@ public function '.$relation['relation_name'].'()
7676
*
7777
* @return array
7878
*/
79-
private function _getTableRelations()
79+
private function _getTableRelations(): array
8080
{
8181
return [
8282
...$this->getBelongsTo(),
@@ -86,19 +86,21 @@ private function _getTableRelations()
8686

8787
/**
8888
* Extract the table name from a fully qualified table name (e.g., database.table).
89-
* @param string $foreignTable
89+
* @param string $foreignTable
9090
* @return string
9191
*/
92-
protected function extractTableName($foreignTable)
92+
protected function extractTableName(string $foreignTable): string
9393
{
9494
$dotPosition = strpos($foreignTable, '.');
95+
9596
if ($dotPosition !== false) {
9697
return substr($foreignTable, $dotPosition + 1); // Extract table name only
9798
}
99+
98100
return $foreignTable; // No dot found, return the original name
99101
}
100102

101-
protected function getBelongsTo()
103+
protected function getBelongsTo(): array
102104
{
103105
$relations = Schema::getForeignKeys($this->table);
104106

@@ -123,7 +125,7 @@ protected function getBelongsTo()
123125
return $eloquent;
124126
}
125127

126-
protected function getOtherRelations()
128+
protected function getOtherRelations(): array
127129
{
128130
$tables = Schema::getTableListing();
129131
$eloquent = [];
@@ -132,7 +134,6 @@ protected function getOtherRelations()
132134
$relations = Schema::getForeignKeys($table);
133135
$indexes = collect(Schema::getIndexes($table));
134136

135-
136137
foreach ($relations as $relation) {
137138
if ($relation['foreign_table'] != $this->table) {
138139
continue;
@@ -158,7 +159,7 @@ protected function getOtherRelations()
158159
return $eloquent;
159160
}
160161

161-
private function getUniqueIndex($indexes, $column)
162+
private function getUniqueIndex($indexes, $column): bool
162163
{
163164
$isUnique = false;
164165

src/stubs/Request.stub

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace App\Http\Requests;
3+
namespace {{requestNamespace}};
44

55
use Illuminate\Foundation\Http\FormRequest;
66

src/stubs/livewire/Create.stub

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ namespace {{livewireNamespace}}\{{modelNamePluralUpperCase}};
44

55
use {{livewireNamespace}}\Forms\{{modelName}}Form;
66
use {{modelNamespace}}\{{modelName}};
7-
use Livewire\Attributes\Layout;
87
use Livewire\Component;
98

109
class Create extends Component
@@ -23,7 +22,6 @@ class Create extends Component
2322
return $this->redirectRoute('{{modelRoute}}.index', navigate: true);
2423
}
2524

26-
#[Layout('{{layout}}')]
2725
public function render()
2826
{
2927
return view('livewire.{{modelView}}.create');

src/stubs/livewire/Edit.stub

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ namespace {{livewireNamespace}}\{{modelNamePluralUpperCase}};
44

55
use {{livewireNamespace}}\Forms\{{modelName}}Form;
66
use {{modelNamespace}}\{{modelName}};
7-
use Livewire\Attributes\Layout;
87
use Livewire\Component;
98

109
class Edit extends Component
@@ -23,7 +22,6 @@ class Edit extends Component
2322
return $this->redirectRoute('{{modelRoute}}.index', navigate: true);
2423
}
2524

26-
#[Layout('{{layout}}')]
2725
public function render()
2826
{
2927
return view('livewire.{{modelView}}.edit');

src/stubs/livewire/Index.stub

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ namespace {{livewireNamespace}}\{{modelNamePluralUpperCase}};
44

55
use {{modelNamespace}}\{{modelName}};
66
use Illuminate\View\View;
7-
use Livewire\Attributes\Layout;
87
use Livewire\Component;
98
use Livewire\WithPagination;
109

1110
class Index extends Component
1211
{
1312
use WithPagination;
1413

15-
#[Layout('{{layout}}')]
1614
public function render(): View
1715
{
1816
${{modelNamePluralLowerCase}} = {{modelName}}::paginate();

0 commit comments

Comments
 (0)