1. Frameworks Execute The Same Code Repeatedly Without Need
Rasmus clarified that all frameworks that are for general purposes are not optimized for everbody's needs.
A more specific complaint was that the solutions that frameworks offer lead to executing needless PHP code repeatedly in every HTTP request. The example that Rasmus gave is that in every request frameworks check the database type the application is using to load the respective database access class. Since the database type does not change after an application is deployed, he sees this as a waste.
While I agree with Rasmus, I think this example is not very compelling because checking the configuration to decide which database access class to load takes a very small fraction of time, especially when compared for instance with executing database queries, which usually take many milliseconds and sometimes take a few seconds to run.
A better example of this problem is when frameworks need to read configuration files to define load the actual configuration values.
Often frameworks read configuration from INI files. PHP has built-in functions to load and parse INI files. Despite you can do it all with a single function, reading a INI file and parse it takes some time that is usually way more than checking the parsed configuration values.
If your framework reads and parses configuration values from files in other formats that PHP does not have built-in support, like for instance YAML or XML, things get worse because the frameworks have to do the parsing in pure PHP code. That is much slower than the C code of the PHP engine that parses INI files.
A better alternative is to have configuration values defined in PHP script files. Just put the configuration values in PHP scripts that assign the values to variables.
When you use a PHP caching extension, PHP scripts are only compiled once. On a second run, PHP scripts compiled into opcodes are loaded from RAM. That is much faster than loading configuration from files.
2. Frameworks Require Too Many Interdependent Classes
Another point that Rasmus mentions is that sometimes you need only specific parts of a frameworks, but since the framework classes have too many dependencies between each other, you need to load too many classes even when you use simple features of the framework.
While this is true to a certain degree, I have seen efforts from certain framework developers to reduce the dependencies between distinct components. Still there are often dependencies between many frameworks classes that sometimes do not aggregate anything to an application with specific needs.
To address this problem some developers need to change the frameworks to strip the needless parts that add overhead. This causes a maintenance nightmare because they need to do that every time they want to upgrade to a newer version of a framework they started to adapt for their needs.
Rasmus suggests using frameworks optimized for specific purposes to avoid this problem. He recommends using for instance Wordpress or Drupal if you just want to publish a blog.
Alternatively Rasmus suggests that frameworks provide a means to let the developers push to production just a small subset of the components that are needed in each application.
This solution is too general. Rasmus did not get to the way certain frameworks implement things and so he did not comment on why certain frameworks need so many components.
For instance many frameworks rely on runtime ORMs (Object Relational Mapping). These are components that let developers define how to query databases treating information as objects, rather than tables of records.
Object orientation is fine for abstracting problems and encapsulating solutions into classes of objects, but the way certain ORMs work adds too much needless overhead.
The developer has to write code to dynamically specify the class variables (tables fields), condition clauses, object relationtionships (table joins), etc... to compose the actual query at runtime. This adds a lot of overhead because the queries that are executed are the same on every request, apart from some parameter values that may vary.
There is a better solution that avoids this overhead. Instead of dynamically composing queries at runtime, just have a separate tool that generates PHP code for the ORM classes. The generated classes already have the compiled SQL queries to execute without further overhead at runtime.
I have been using this approach since 2002 when I developed a ORM tool named Metastorage. It does exactly what I described above. I define in project file the objects, variables, relationships and functions that I need to apply on objects.
Metastorage processes my objects definitions and generates ORM classes that execute the necessary queries at runtime just by calling the classes functions. No query building is done at runtime.
3. Needlessly Complicated Solutions
One thing that Rasmus did not mention directly is about the complicated solutions that frameworks tend to push.
That is the case for instance of application version migrations. Some frameworks have copied the concept of migrations from Ruby On Rails. This means that you have to write code to change your database schema between different application versions.
This is another thing that Metastorage addresses in a more efficient and less painful way for developers. Metastorage generates database table schema definitions in a separate file from my object definitions. It generates an installation class that installs the database tables on the first time.
If I change the object definitions, the installation class can also upgrade the schema with the newer definitions without destroying any data already inserted in the database tables.
This certainly makes development much faster and application upgrades less error prone because the tool always generates correct code to upgrade the database schema. When you write migrations code by hand, you may make mistakes that make you spend more time and effort to fix.
4. Duplicating the Web Server Functionality
Another aspect that Rasmus did not mention directly is related with aspects that frameworks sometimes require that PHP code redoes work that the Web Server already has done.
For instance, routing is the processes of assigning some code (a controller) to handle requests with different URL patterns. Many frameworks push applications to use the front controller pattern. The front controller analyzes the request URL and load a specific controller to actually handle the request.
The matter here is that the Web server already does this. It can match the request URL against configuration (for instance of mod_rewrite or similar) and execute the appropriate PHP script.
When you make PHP handle the routing process, you are adding needless overhead to perform a task that is the same for every request with the same URL pattern. This falls into Rasmus complaint of frameworks that execute the same code repeatedly to the reach the same outcome.
This seems to be yet another bad influence that PHP frameworks got from Ruby On Rails and Java. With those languages the Web server forwards the request to an application server.
PHP does not need to work this way because it always runs integrated with the Web server, so there is no point duplicating the Web server functionality in a way that is slower and adds more overhead.