Hello. I have the action add() defined in ProjectController.php for the route ‘/project/add’ which authenticates users via Google OAuth, and then displays an empty form page on GET. This action also handles all the logic during POST involving processing multiple uploaded files, and other form fields across multiple database tables.
I want to add an API to my application. I’ve created the action add() in separate controller, ApiController.php, for the route ‘/api/add’. This route authenticates via header token.
Since completely duplicating the code is incorrect, how do I call the add function in the Project controller from the Api controller, sending it all the form data? Do I simply instantiate a new ProjectController within ApiController, and call the function?
The CakePHP5 Book makes it very clear that the ‘Model’ is for database access.
I see two solutions, certainly open to something more Cake-idiomatic.
Create a new class with a single static function which accepts ServerRequest. From both controllers, I can call this function, and pass the incoming $request, handling any errors via try-catch.
Extremely similar to 1, make a trait with the logic in a private function. Include this trait in both Controllers, calling/passing as needed.
Any other solutions? Is #1 or #2 better than the other?
Option 1 is easier to unit test, and perhaps more flexible. I wouldn’t make it a static function, though, I’d make it a service class, maybe you even do something like pass the request to the constructor. Lots of variables about how you do this, whatever works well for you is the right answer.
IMO, traits are best for when you need the exact same functionality in multiple places. Because you have different authentication, output and error handling requirements for API vs “normal”, it feels to me like this is not that situation.