So basically it's an OOP vs Procedural debate now? Chaining methods in this manner sacrifices: Polymorphism - I can't substitute a method with another method very easily (I need to use inheritance just to achieve this). And Encapsulation - The application state is shared among every controller action.
The problem here is that as far as I'm aware, most programmers are not clairvoyant. Look at the example from earlier, it wasn't written this way to begin with and in most cases wouldn't ever be. You, the application developer has had to go back and modify code which is currently working 100% for its original goals. You've gone back and re-structured the entire application based on the needs of a change which happend after-the-fact. This means re-testing all your old code and making sure you haven't broken anything.
I see and acknowledge that repeated code. Though, I'm skeptical that the best solution is rearchitecting the whole system. It seems to me that common code between any two controller actions could be resolved simply with a private method within the controller. For example, if you wanted to isolate the list rendering code or the data fetching code:
As I said, it's an OOP vs procedural debate at this stage. In OOP it's easy to substitute any part of the application. Now you've moved it into a procedural level by passing state between functions this isn't possible without hacks such as inheritance (Which isn't the right tool for this job, and creates immense scalability issues). Try to completely change the implementation of getPostsByUserId() for a specific controller but keep everything else the same. Nope. Not without a dodgy workaround or changing the controller code and repeating logic.
Forgive me, but that code is far from self explanatory. Pagination logic involves knowing the total number of records, the number of records to display per page and what page is currently being viewed. I can see none of that there.
Pagination can be and is reused. In templates, it would look something like this:
It's not just the processing though, it's the display logic surrounding the form. The logic for whether the view should show any errors, what variables are available in the view, etc.
Form processing can be and is reused. The form itself and validation rules are defined in their own classes, so all the controller has to do is:
Two queries are run. Only one is actually coded. There is a difference here, it's subtle i'll admit but it's important. The distinction is that each MVC triad has its own state and can be isolated within the application. At the same time, any part of either of the triads can be substituted for something else. I could be, for instance, comparing the posts in one database to the posts in another by substituting the model in one of the triads. There would be 4 classes defined, two models, one controller and one view. Both instances of the view would be of the same class (but different instances), both instances of the controller would be the same class (but different instances) and the two models differ entirely, they could have different dependencies, different configurations, anything. But since they're loosly coupled to everything else and abide by encapsulation rules, this isn't a problem.
Now that we've isolated the data fetching code, I think it's straightforward how you would reuse it. Your own code, in fact, also makes two different queries, and it does so in your WireItUp code, which we already know is analogous to a framework controller. Moreover, your own code also passes two data sets to the view. Your compareTwoUsers template is passed "user1" and "user2".
This is where the flexibility happens. Because OOP affords us Encapsulation and Polymorphism, I can re-use and substitute in and out any of the components with ease. Using procedural style methods in a "controller" class limits this flexibility. You're tied into an implementation because it has to be $this->method(). You can work around that in a very ugly way with inheritance but your controller is still forced to know of all the dependencies used by any of the methods. In my database example, it needs access to a model which accesses the first database and a model which accesses the second database. Not good!
This is messy. It reduces portability because nothing is isolated. I can't just copy certain features between projects because everything is tied together. In my other project I want the list posts by users funtionality but there is only one database so I the compare 2 databases method wont work... and I can't even initiate the class because the second dependency doesn't exist.
It's very basic OO theory: A class should have a single responsibility. It affords it reusability and will inevitably mean it has fewer dependencies making it portable as well.
I'd argue the reason that few people do this because Symfony controllers have too many responsibilites (See Flaw: Class Does Too Much. Each controller action in Symfony is performing a single task. In OOP this should be its own object. And why does a controller have a render method?! That's absurd. It's clearly view logic!
Normally I'd have to grant you this one, but in Symfony, extending the base controller is completely optional, and it exists only for convenience. The Symfony docs/book goes on to describe how you can define your controllers as standalone, injectable objects. My impression is that not many people using Symfony bother to do that, and the reason, I suspect, is once again effort vs payoff. An injectable object is typically easier to unit test, but in this case, unit testing a controller pretty much means you're actually doing functional testing, and it's actually more convenient to fill your database with test data than it is to create a mock doctrine object for injection. A standalone, injectable controller would also be easier to transplant into any other framework, but since no one ever really intends to even try that, this is another payoff that will never materialize. And so people typically opt for the convenience of the base controller.
Why is it view logic? Because the controller should not be concerned with any implementation details about the view. As it stands, the controller initiates the view which means it's impossible to use a different template system without modifying the controller! That is truly ridiculous.
I think you missed the point here.. but again it's an OOP vs procedural debate.
In Symfony, pagination logic exists in one place within the controller, and one place within the template. I showed above how query logic can be isolated, and templates can use either "include" or "render" to reuse template partials or to reuse the output from other controllers.
This was the point I was getting at. "Template partials" are pointless because you have to supply the data to them, which means fetching it from somewhere and repeating the data fetching logic. I want to pull in a stateful object. I want a reusable component. I want to call a simply functon such as $this->getView('/user/details/123'); from any other view and without any additional work have it pull in a table of details for a specific user.
Actually, this hits the nail on the head. This is why using a controller action to configure the application is a bad idea. It's not easily reusable so you can't instantly create a MVC triad with the same configuration from anywhere, it's tied to the outside world.
This was about Views being reusable. They simply ARE NOT in Symfony. You must supply the data every single time you use a view which means at worst re-writing the data fetching logic or at best re-writing the binding logic each and every time. In MVC you create the views and pass it a model and everything just works.
I don't claim to be an expert at Symfony, I don't like it because it uses PAC. That's what I have a problem with, Symfony itself is irrelevant.
Based on all the above, it seems there's an awful lot about Symfony you didn't know, and your assumptions about it thus far simply haven't been accurate.