Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using LCG with Laravel-Modules #105

Open
larry-tx opened this issue Feb 11, 2019 · 2 comments
Open

Using LCG with Laravel-Modules #105

larry-tx opened this issue Feb 11, 2019 · 2 comments
Milestone

Comments

@larry-tx
Copy link

larry-tx commented Feb 11, 2019

Environment:

  • Laravel-Code-Generator Version: 2.2.12
  • Laravel Version: 5.7.25
  • nwidart/Laravel-Modules: Version: 4.0.0

Description:

Modular Development

I am working on a very complex web application. In order to make it more manageable, I've chosen to go with a modular system as implemented by laravel-modules I certainly don't expect you to accommodate a package by another author, modularity has become one principal way to use any framework in a complex application. Hopefully, you'll be able to give me some guidance in making use of your outstanding package.

I'm sure that CrestApps is familiar with modular development, but please indulge me a bit of explanation to avoid any confustion. A module should be entirely self-contained. That is a module should encapsulate its own migrations, models, controllers, view, routes, etc. If someone wanted to use a module that I created in their Laravel app, I should be able to simply copy a module folder from my app (e.g., «ProjectRoot»\Modules\Network) and hand it off to the other person. That person would simply paste the module folder in their application, run the module-specific migration found, not in «ProjectRoot»\Modules\Network\Database\Migrations but in «ProjectR00t»\Modules\Network\Database\Migrations. Of course any given module could easily contain many models and associated controllers, views groups and so on.

One of my modules that I repeatedly reuse is Common which ontains the associated models, controllers, etc. for these tables, among ten others others:

  • common_states containing the States of the U.S. and provinces of Canada along with their approved abbreviations and so on.
  • common_zip_codes containing the latest U.S.Postal Service Zip Codes along with associated city names and so on.
  • common_ingredient_units containing common English and Metric units, such as cup, teaspon, tablespoon, pound, ounce, along with assoicated abbreviations, conversion to the other measuring system, and so on.

Because the data from these tables needs to "migrate" with the module, I've modified my migrations for the module to not only create the associated tables bu to also insert the data.

Basically, where I'm having difficulty is in the location and namespacing of some of the files generated by LCG. The structure of my modular applications looks like this:

  • «ProjectRoot»\Modules\Network\Entities (Location of models)
  • «ProjectRoot»\Modules\Network\Http\Controllers (location of controllers)

Thus, for each module (using here, Network as one example, of many, many modules) has a structure that parallels the whole project structure.

Hopefully, these example make it clear why modules are absolutely essential to any Web app that is beyound the merely trivial

Because of the way that Laravel handles resources, begrudgingly I've chosen to put my views under «ProjectRoot»\resources\views instead of the «ProjectRoot»\Modules\«ModuleName»\resources\views path. I'm entirely negotiable on that point. Actually, as with most most modular development, I place the primary source views files under the Module/«ModuleName»/resources/views directory in order to maintain the basic principles of modularity and "publish" them to the «ProjectRoot»/resources/views in order to accommodate Laravel.

CodeGenerator and Modular Development

I've tried using the published user-modifications for CodeGenerator to achieve the principles of modular development.

For instance, CodeGenerator put the principle files (model, controller, request) in the path «ProjectRoute»\app\Modules\Network\Entities, «ProjectRoute»\app\Modules\Network\Http\Controllers, etc. rather than «ProjectRoute»\Modules\Network\Entities despite the fact that the custom config file had 'models_path' => '/Modules/Network/Entities',. It would appear that the package code has something like app_path( '/Modules/Network/Entities') rather than base_path( '/Modules/Network/Entities') to compute the location of the models.

Other (mostly non-modular but related issues

My routes are a little more complex. I don't like the use of the "admin" sub-directory, preferring instead to simply specify the route with an admin group. For instance, I know that my Network module will always be within the admin route group with associated permissions. On the other hand, the index and show views of portions of my HomeAutomation module will not be under the admin route group while the create and update views will be.

Actually, I prefer a routing group/sub-group(s) structure like this:

Route::group(['prefix' => 'admin'], function() {
	Route::group(['prefix' => 'network], function() {
		Route::resource('devices', \Modules\Network\NetworkDevicesController);
	});
});

To produce a URL like:

	https://example.com/admin/network/devices/index

The beauty of routing is that I can discard th reference to "Modules" (important for the developer but totally irrelevant to the user) and the duplicative "network" in "network_devices" (important in keeping the database organized but, again, irrelevant to the end-user). And I can put routes under the "admin" group and not if inappropriate. That often means busting up a resource groups (create/store/update/destroy under admin, the rest not.

Again, there doesn't appear to be a way to specify all of this in CodeGenerator, and it may be that it just isn't feasible. Nonetheless, I'd definitely put it on a wish-list for feature enhancements.

CodeGenerator should be able to put the routes in the appropriate location («ProjectRoot»\Modules\«ModuleName»\Routes\web.php) instead of willynilly appending the routes to «ProjectRoot»\routes\web.php. I can't imagine what a gargantuan, monstrous, horrendous mess folks' web.php file must become without splitting up routes to where they are related. Even with code-folding in PhpStorm, that would be totally unmanageable.

mwidart/laravel-modules does an outstanding job of merging routes at runtime, as do most module packages. That's also a reason for structuring routes as nested route groups. A route like admin/common is not going to get merged with the admin group creating yet anothr mess.

This next is actually on my wish list for Laravel, as opposed to CodeGenerator, although it is doable via using a ->where regex in the route. Research repeatedly demonstrates that underscores introduce a hight degree of likelihood for typos in URLs (and practically everywhere else). In non-code-oriented users, they also create a high degree of frustration. I prefer that, at least, the model-specific portion of the route be dashed like this:

https://domain.com/admin/network/network-device-types/index.php

for the NetworkDeviceType model within the Network module. Most other frameworks either do this automatically or offer a dashed-route parameter.

Another thing that I haven't seen in CodeGenerator is support fir JSON (MySQL) fields which Laravel does support as "Associative Arrays" (Objects). In the Laravel blogosphere, these have become a hot item. I still haven't decided if my use cases warrant them, but they do have the potential for reducing the number of table columns for infrequently used cases (three lines in addresses, name-suffixes for credentials, other suffixes like Jr., Sr., III). I really hope that these are on your radar with a soon-to-come version update.

Steps/Commands To Reproduce:

  1. I produced a CodeGenerator_custom.php file; see the .txt file below. (Github won't permit attaching a file with a .php extension.)
  2. I executed the following command in a bash terminal.
    php artisan create:resources NetworkDevice --routes-prefix "admin/common" --models-per-page=15 --with-form-request --with-auth --table-name "network_devices" --table-exists --with-soft-delete --with-migration --force
  3. CodeGenerator put the views files in «ProjectRoot»\resources\views\admin\network. Unfortunately, the path should have been «ProjectRoot»\resources\views\admin\network\network-devices (or whatever variation on network-devices is wanted) if these files cannot be put under the Module. In any case, the issue with the structure still remains. NetworkDevice is just one of many models — along with controllers, views, etc. — that form the the Module Network.
  4. CodeGenerator created the following route (portions truncated for brevity):
    Route::group(
        [
            'prefix' => 'admin/network',
        ], function () {
            Route::get('/', 'NetworkDeviceController@index')
                ->name('admin.network.network_device.index');
    });

This route will work actually quite well, although I'd prefer a dashed route (i.e., admin.network.network-device.index). If I could have more control over the generated route, what I would create manually would be more like admin.network.device.index in order to avoid repeating "network." I use the "network_" in the table name to better manage tables. The route clarifies that on its own.

In the End What's Needed

That's a very long way around describing what I'm trying to do. Here's the problem what I'm having: It's fairly easy to make changes to your package that have to do with templates. Being new to Laravel, it took me a while to get use to making template alterations, but I think I've gotten the hang of those. Where I'm having problems seem to be in other areas:

  • The places where files are put.
  • The ability to specify routes and route groups.
  • The ability to specify a module with its impacts on the location of files, construction of routes and so forth.
    I know that I could fork your repo (privately, my Laravel skills aren't that good to do otherwise). You've done an outstanding job of continuing development of CodeGenerator, and I want to be in a position to take advantage of all of those. Forking, that would effectively cut me off from future developments of CodeGenerator. What I'm hoping is:
  • That I've missed something in the instructions for CodeGenerator and that much of what I've covered can be accomplished in what's there already.
  • That, if there is anything that isn't covered by the existing CodeGenerator, you will be able to incorporate in a future version of the product. With things like modular development, you could spur Laravel developers out of the trivial and into more modern development.
  • That, if there is anything that you consider to narrow a use case to incorporate into CodeGenerator, you can provide me with any developmental strategies that would minimize the diffficulties involved in incorporating future CodeGenerator versions.

Content Of The Resource-File:

network_devices.json.txt

Content of the Custom CodeGenerator (config) File

codegenerator_custom.txt

@MikeAlhayek
Copy link
Collaborator

Agreed! When time permits, I'll be sure to add support for module-based development.

@elemes1
Copy link

elemes1 commented Mar 20, 2019

@Larrytx this was my first thought when I saw this package, it would be an interesting feature to have +1

@MikeAlhayek MikeAlhayek modified the milestones: 3.x, backlog Jan 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants