Newbie code layout question

Hi all,

I wondered if I could get some advice on the “best” way to lay out my code. My long-term goal is to rewrite much of our current out of date system in to an API. api.domain.tld will be the top level domain and different features will be specified with groups. The first project is the orders returns system and will be found at api.domain.tld/returns

I am using Propel ORM and practically all model code will be in the generated classes.

My own classes are in src/, propel classes are in generated-classes/ and slim and other components are in vendor/, installed with composer. My index.php file lives in public/, where I setup $app. Inside there I will have several groups, for instance my returns group:

$app->group('/returns', function () use ($app) {
    $app->get('/list', function ($request, $response) {
        // ...
    $app->post('/add', function ($request, $response) {
        // ...etc

Now, requests will need just a little but of model code, for instance instantiating an OrderReturn object and either outputting it as JSON or updating some values and saving. Would it be best to put the model code directly in there, or would it be best to have an invokable class and add it as middleware to the group? For instance a Model class that performs actions depending on the $request. Or is there a better way here, bearing in mind that eventually there will be a lot of groups and routes. I actually don’t mind them all being in index.php as such, but that could get very big if the actual code is in the index.php file.

I hope that makes sense, please ask if I can give more information as I’m probably missing something :slight_smile:

I think your current approach is not very scaleable (from a code-perspective). I would suggestion you implement controller classes, whose methods you then put in your route definition. It’s definitely much more readable than putting code directly into the route definitions.

My routes.php looks like this (and I would say, is very readable):

$app->get  ('/faq',                         'App\Controller\UserController:faq')->setName ('faq');
$app->get  ('/helpdesk',                    'App\Controller\UserController:helpdesk')->setName ('helpdesk');
$app->get  ('/helpdesk/{id}',               'App\Controller\UserController:helpdeskTopic')->setName ('helpdesk_topic');
$app->get  ('/login',                       'App\Controller\UserController:login')->setName ('login');

Hopefully this answers your question and helps.

1 Like

Thanks, I just read some of your other posts with similar/related information and I agree, especially in my case as these “controller actions” can work directly with the Propel model classes - it all seems need and compartmentalised :slight_smile:

Thanks again

these “controller actions” can work directly with the Propel model classes

While I don’t know Propel, I’d be careful about binding your routes directly to Model classes. The Job of a controller function is to acquire, validate, prepare data, etc. This of course all depends on your use case, but I’d say that there is a pretty good architectural case for not binding routes to your Models directly because even in the most basic case, your controller needs to acquire the data from somewhere and your Model has no business knowing about how to acquire this data.

I get your point - thanks. I think I explained it poorly. I meant I can call call model functions from the controller actions, something like:

public function view($request, $response, $args)
    $return = OrderReturnQuery::create()->findPK($args['id']);
    return $response->withJson($return);