Should we remove controllers from MVC?

Controllers are often bloated. By which I mean, they contain business logic when they should contain only glue code. I believe removing controllers entirely and replacing them with ControllerAction classes can remedy this somewhat, where each controller method becomes a ControllAction class. Another solution is to replace them by middleware and use a pipeline pattern through and through.

Counter arguments:

If controllers contain too much business logic that’s not the controllers fault of the concept of controllers, it’s a stupid programmer’s fault.

I want a framework that teaches (and enforces) good practice, not necessitates it.

It’s wrong to remove a well working concept just because people are too stupid to use it.

I actually do think it’s the tool’s fault if it’s being abused. :slight_smile: At least when the tool is a framework.

One could also argue that traditional MVC controllers violate the single-responsibility rule - one URL, one class; not multiple URLs, one class.

In case controller contains business logic, extracting all its actions into separate classes won’t help much. Business logic still would be in the wrong place.

In Yii 3 we are using middleware but still we allow using callbacks as middleware so one can point multiple URLs into a single class. Sometimes it makes sense.

1 Like

“Wrong place” doesn’t matter as much as “separated”, IMO.

But Yii 3 still recommends one controller with multiple actions? Won’t scale. :wink: On the other hand, you can only be so much non-idiomatic without losing traction, even if it’s “correct”.

In Yii 3 we are using middleware but still we allow using callbacks as middleware so one can point multiple URLs into a single class. Sometimes it makes sense.

Do you support not using controllers at all, only middleware for a given route?

Yes, there’s no more Controller class you can inherit from and method signature is PSR-15 middleware.

Yes, there’s no more Controller class you can inherit from and method signature is PSR-15 middleware.

Well, that’s positively awesome. :slight_smile: But no next() call? Is the position in the middleware pipeline hard-coded? And maybe you can point me to where routing is configured…?

Based on this code: https://github.com/yiisoft/app/blob/master/src/Contact/ContactController.php

There is no need for action handler to pass handling to next middleware since it forms the response itself. Other middleware may do it though:

Thanks for the answer! Does Yii 3 also support invokable controller classes as in Laravel? That is, instead of

Route::get('/basic-auth', [SiteController::class, 'auth'])

you have

Route::get('/basic-auth', SiteAuthController::class)

?

That’s just syntax sugar for Route::get('/basic-auth', SiteAuthController::class, '__invoke'). Currently it’s not like that.

I forgot to mention one thing. Despite the syntax looks like these are static callbacks, these aren’t. Controller class (that we often call action handler) is instantiated from container. You can find more details in docs.

OK. Would you accept a PR for this syntactic sugar? Controllers with x action methods do not scale, and I want to delete them - forever!

I agree this is often the case in poorly designed or hastily written (in the sense that the author didn’t take the time to write proper code) applications. It sure isn’t the case all the time though.

Removing a feature because certain users of the framework misuse the feature is not sane. There are endless ways of misusing software, so if you want to prevent misuse or bad programming by removing features that are misused, you’ll end up with nothing.

There are already action classes in Yii, see: https://www.yiiframework.com/doc/guide/2.0/en/structure-controllers#standalone-actions

You’re already using one that encourages good practice, see: https://www.yiiframework.com/doc/guide/2.0/en/structure-controllers#best-practices

This could be made more prominent though, that’s for sure. But at the same time, and I think this is very imporant, please realize that pretty much everyone who actually took the time to understand MVC does know that controllers should be thin.

In other words, if you don’t know this, you haven’t educated yourself enough, and this sure as heck isn’t the frameworks fault. We can’t expect a framework to educate people on the basics or fundamentals that they should already know by themselves. Just like you are expected to actually know how to write PHP code in order to use a PHP framework. The framework documentation should indeed encourage best practices and inform the user about the important ones, like Yii does in the guide above, but it’s still a framework and not a programming class.

I have written numerous MVC applications using Yii. There’s not a single controller in any of these applications that would be considered fat. Not a single one. I am not saying I’m a good programmer, I certainly don’t think I am, but I did my research. I know (at least somewhat) what MVC is about, and I know how to write proper code with it. There’s also a lot of common sense aspect to this topic.

Still you are telling me that because other people haven’t done their research, are copy-pasting code to just make things in their applications work, without even understanding what the code they’re copying actually does, and/or don’t care enough to write clean code, you want to take away a core part of the framework, which is also an extremely established pattern (with a lot of great success, considering how many working applications there is out there that’s MVC based)?

Sorry, but you are totally barking up the wrong tree here. You should be focusing on improving the documentation instead of removing stuff because people can’t write proper code. I honestly find it annoying that you suggest what you’re suggesting. Teach people to write proper code instead, and this won’t be a problem (if it ever was - if others want to write shitty code, then there’s nothing you can do to stop that anyway).

Even if this is violated, it can work perfectly well and be perfectly fine. Don’t overcomplicate things, also realize that there’s a lot to being pragmatic and that you can always refactor your code if you need to (as long as it’s clean and properly written).

If you truly want that single responsibility, you can use the other types of patterns there are. You don’t need to remove Controllers in Yii to do that.


Finally, bad programming, bad code and misuse of features in e.g. a framework isn’t something that comes from bad framework design. Yii doesn’t encourage bad programming, in fact it does the opposite, as shown above.

Bad code often comes from people not caring or not being skilled enough or lacking common sense, and that is not something that you can control entirely using the design of the framework. You can contribute to good practices by writing good documentation, but in the end, if people want to sit and copy-paste code in such a way that they just get stuff working, without caring about code quality, this is nothing you can ever put a stop to.

And after all, those people don’t care enough or have the resources to do so anyway, so let them write their crappy code and the rest of us can write clean code. Just don’t take away features in the framework just because others misuse them.

A better option would be to improve the Controller documentation in the Yii guide and the API docs, such that it’s even more clear that controllers should be thin. Just putting a notice at the top of the Controllers section in the guide, pointing out that controllers shouldn’t contain business logic, might help a lot.

2 Likes

Yes, at this point I wouldn’t remove anything since the practice is so established, but I’d like to see the possibility of making one-action controllers idiomatic in Yii 3. As they are in Laravel.

There are two different discussions, really:

  1. What I consider best practice
  2. How a framework can best be adapted to allow for that practice (including getting through a PR that’s accepted by the maintainers and community)

Yes, but:

To use a standalone action, you should declare it in the action map by overriding the yii\base\Controller::actions() method in your controller classes like the following:

So it’s actually not available the same way as a traditional controller.

There’s also a difference in fundamental philosophy between us, which is no point discussing, only acknowledging: Good tools, for me, limits the programmer. That’s why languages like OCaml and Haskell are “better” than PHP, Ruby, C, etc. Again, this is more about personality than anything technical, I think, but it’s my starting point and why I think frameworks need to do better than today. Which they will. Because people keep improving them. :slight_smile:

Yes. That should be Route class, validateMiddleware().

Thanks for illustrating your attitude clearly.
Just to put one different voice in the ballot:
By no means do I want software to teach me anything.

Esp. I liked Yii in the first place, and would appreciate to see this attitude continued in 3.0, because it leaves it to me to decide how much abstraction to use - for example leave ActiveRecord aside completely and use the DB’s SQL ‘attitude’ directly.
For programmers or teams who chose to be disciplined by their tools, there are fine choices elsewhere on the market.

This works good for senior devs, but it leaves the risk that the juniors will misunderstand and misuse the basic design patterns provided by the framework. Basically you need disciplined code reviews to make it work (maybe you always do). It would be good if the framework, language and tools could do some of that work automatically.

My perspective is a big, old project with 50+ contributors over a long time period (10 years or more).

Maybe then Yii is not the ideal framework for you.
I understand your attitude, I worked in the SAP field most of my computer business career, and decided to leave it.
There should be a good PHP framework for smaller teams, and IMHO Yii is a viable solution for this segment.

What makes you say/think that Yii is better for small apps/teams? Compared to other frameworks.

Fox example, it does not enforce the use of AcvtiveRecord.
There are applications where a shorter path to the DB is advantageous.