We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Keeping Micro Framework Code DRY

Since in Micro applications we don't have the Dispatcher, I'm trying to understand what's the best way to approach reusing identical sections of code within a controller or potentially across them.

As an example, in my app I have User Registration and Login functions, they're both within the same controller, however, once a user registers successfully, I'd like to go through all the same actions that I would if they were logging in with their new account, but do it immediately. Ideally, I'd actually just call the Login function and let it access all the same POST variable data that the Registration action used to register the user.

Better yet, having a separate login function that can take a user model and do the necessary actions to log them in and simply having the login function and registration function pass the user model they pulled from the database would be ideal.

With Micro applications, what's the best practice for this? I can't seem to figure out how to use private controller functions across multiple actions without it throwing an error, and without the dispatcher it seems I can't just call another action within the same controller.

You can just use services, put code which should be used between diffrent endpoints into new class and add it to di and access it in request handler. At least i would do it like this.

edited Oct '17

That seems like an awful lot of boilerplate code for my example, where really I just need to have a performLogin() function that gets run and passed a user model by the Registration and Login endpoints on my API once they've done their lookups.

Perhaps the only complicated issue there is that the function needs to be able to access the session to set some values.



9.7k

You might find something of interest in https://forum.phalcon.io/discussion/16365/mvc-or-micro-or-middle In summary, you can minimise services in several ways.

edited Oct '17

I'm not sure I understand what you want to achieve?

'Middle' app is the way to go for sure, but what common logic you need to access depends on your use case. Can you do it in base controller, as all child controlers inherent from that base controller?

edited Oct '17

I'm already using a middle app, however, I'm trying to figure out how to abstract out common functionalities between two routes on the same controller, or even potentially if they were on different controllers. In this case, once a user has registered or successfully authenticated, a common return should be sent back from both routes. Currently I'm duplicating code between the routes, when I'd rather just call a function which I pass the relevant info.

It's possible I'm just out of the loop on modern PHP classes, but I tried creating a private function within the Controller class and calling that from both routes, but I got errors, I assume because of the scope change when calling an internal function, not sure.

To be specific, this code is repeated in both routes, just different public functions in the same controller class:

$this->session->set('user',
       ['email' => $user->email,
        'name' => $user->name,
        'id' => $user->id
       ]);

    return ['authenticated' => true,
            'user' => [
                        'name' => $user->name,
                        'email' => $user->email
                      ]
          ];

And I'd love to put it into a separate function that I pass the $user I retrieved from the database in both cases.



145.0k
Accepted
answer

On the same controller - add it as method to controller.

On diffrent controller - add it obase controller.

Or use services.

edited Oct '17

I was being dumb and forgetting to use the $this keyword to call a private member method, bad C++ habit, so I was getting the error from that. Thank you all for taking the time to try to help, knowing to look into services or using a base controller might save me time in the future though.