Magento 2: Sending a Custom Header/Response from a Controller
First, this answer, while correct in the fact that it works, is not correct because
- It’s returning
null
, which violates the controller interface contract (see below) - It’s using a global response object, and relying on global state is consdered “bad” (because some other part of the program might change the state during a context you haven’t checked)
- The use of
getResponse
could be considered a dependency that’s not managed via dependency injection, and therefore harder to test. (that gets complicated though, because the base controller class gets the response from an injected context object)
The correct answer is better because it’s not relying on global state. You, as the client programmer, are creating the response object, setting its response code and data, and returning it back to the system. Global state doesn’t enter the picture (assuming, of course, the system implementation itself doesn’t rely on global state for its implementation)
Where things get weird again though is this statement
First of all, to comply with action controller interface MagentoFrameworkAppActionInterface::execute(), your action must return an instance of MagentoFrameworkControllerResultInterface
If you go to the base controller class, you see controllers implement the MagentoFrameworkAppActionInterface
interface.
#File: lib/internal/Magento/Framework/App/Action/AbstractAction.php
abstract class AbstractAction implements MagentoFrameworkAppActionInterface
Then, if you look at the interface’s source
/**
* Dispatch request
*
* @return MagentoFrameworkControllerResultInterface|ResponseInterface
* @throws MagentoFrameworkExceptionNotFoundException
*/
public function execute();
You see the execute
method. The @return
PHP Doc annotataion tells us that a controller’s execute
method should return either a MagentoFrameworkControllerResultInterface
or a MagentoFrameworkControllerResponseInterface
object.
The problem with PHP is, these annotations are not, and can not (without external build processes), be enforced. In a language with a human compile step (like java, C#), when you define a method you must specific a return type. In a language with a human compile step, if you try to
return null
from a method with a return type that’s not null
, the program refuses to run. If PHP had function return types, the less correct answer would have been unrunable.
The end result – “less correct” code will always slip in with PHP. Not because it’s created by “bad developers”, but because using a classic OOP approach in PHP is asking you, the programmer, to do things that the compiler would handle for you in another language.