orchidsoftware / platform

Orchid is a @laravel package that allows for rapid application development of back-office applications, admin/user panels, and dashboards.
https://orchid.software
MIT License
4.46k stars 657 forks source link

Button / Modal method that refers to another screen #2280

Open HichemBenali opened 2 years ago

HichemBenali commented 2 years ago

Problem is: I prefer to keep the business logic in the screens (Or controllers) which causes a lot of duplicate code for the same function.

Describe the solution you'd like Allowing the usage of methods from other screens. Something similar to how laravel's routing works.

Describe alternatives you've considered I have considered using separate classes for the logic but i always end up with duplicate code specially when there is the same functionality in multiple forms. eg: Can create an order from a specific page, or from a quick modal.

tabuna commented 2 years ago

Hi @HichemBenali, as with any religious dispute, there is no one right answer. There are two approaches to this issue: thick controllers and thin models, and vice versa. In the first case, as you might guess, the business logic is located in the controllers, in the second - in the models.

In screens - there was a point, in that you can tell exactly what is happening on it simply by going to this class, where the data comes from, what actions exist, etc. which reduces the cognitive load on understanding what is happening.

I can offer you some good solutions in my opinion for building an application:

Actions

Creation of ordinary classes that perform only one simple "Action" method and can be called from various variations (Controllers, services, console). For example:

namespace App\Actions;

class CreateOrder
{
    /**
     * Generate new order for the user.
     *
     * @param  mixed  $user
     * @return void
     */
    public function __invoke($user)
    {
        // Your code
    }
}

Then call it on the screen:

(new CreateOrder)($user)

Real examples in Laravel application can be seen here: https://github.com/laravel/fortify/tree/1.x/src/Actions There are also various packages that elevate this way of working to the absolute: https://laravelactions.com/ Also read https://stitcher.io/blog/laravel-beyond-crud-03-actions

Services

You can also create a completely new file, in which you would combine actions that can be performed on a certain semantic logic.

namespace App\Actions;

class Shop
{
    public function createOrder($user)
    {
        // Your code
    }
}

This is a slightly more complex option, because it combines a larger area of ​​responsibility.

Model

If the application is small and was not going to be ambitious, then it is very common to see business logic in regular Eloquent models:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    public static function createNewOrder($user)
    {
        // Your code
    }
}

That is, there are a lot of accommodation options and they are different. You can choose according to your taste, in order not to duplicate the code, for example, in the admin panel and the client part of your web application.

Services

Placing directly in the controller makes sense when your code is never needed again in another part of the application. In all other options, it is better to take it out of the controller.

If your code is exclusively distributed to screens and there is no more use for it. Then consider the inheritance option:

namespace App\Http\Controllers\Screens;

class OrderList extends Order
{
   //...
}

Where the order creation method would be defined in the main screen:

namespace App\Http\Controllers\Screens;
use Orchid\Screen\Screen;

class Order extends Screen
{
   //...

    public function createNewOrder()
    {
        // Your code
    }
}

Then the method will be available for calling on both pages.


As I said earlier, there is no unambiguously right or wrong option that I could advise you, but I tried to tell you a few options from which you can choose your own that will suit your project. You can learn more about the architecture of the application yourself, as it is beyond the scope of a simple comment.

As for the subject itself, you can specify any point to send the form from the screen:

Button::make('Go')->action('https://example.com')

To which the POST request will be made