[Docs] When to choose Zend\Expressive over Zend\Mvc #283
Comments
I've been asking this question myself a lot. This is what I come up with so far:
With expressive you can do anything you want. However development time may be longer since you need to add other packages as needed. You can use any package you want and mix and match the way you prefer. At first you will miss the convenience of the predefined functionality like helper functions in controllers etc, but over time you can add this yourself if needed. So basically with Expressive you can be your own architect whereas using Mvc you are sort of bound to its conventions. |
To sum up: Zend\Expressive => micro framework |
It's not necessarily that simple - Expressive is also great if you want to build something bigger and more customized. I have an application that runs Expressive on top of massive legacy ZF1 application and so far it works great - I wouldn't be able to achieve the same with ZF2. For me it looks like this: Zend\Expressive => micro framework for both beginners and experts |
I'm struggling to answer this question myself, and have actually been tasked by our services team to come up with an answer. The reason I struggle is with this assertion by @mtymek:
The problem is that zend-mvc is anything but beginner friendly at this point. You're required to deep dive into the event manager, service manager, and module system essentially from the outset, and these require more than a passing understanding of OOP and design patterns. I also think this statement by @xtreamwayz is interesting:
The problem with full-stack frameworks is that they make a ton of assumptions, and, being general purpose, tend to never do exactly what you need unless your application is in the specific set of use cases the framework was designed to address. This can be summed up in one sentence: The full-stack framework is your architecture. For Rails, that application was a blog and/or basecamp itself. For ZF, we never had a specific use case, though with ZF2, we've been leaning towards APIs and/or CMS development. This has largely meant that to be suitable for any given application, you have to modify the workflow to suit your needs. Micro-frameworks typically address either the API space or deliberately don't address any specific use cases, and instead aim to be a tool to use as a part of your architecture, but not as the architecture itself. With Expressive, we've been keeping the following in mind:
That said, it's also providing architecture: everything is middleware, and you use piping to enable complex behavior. However, unlike a full-stack framework, the developer gets to choose what pieces become a part of that pipeline, versus having that pipeline pre-defined. I suspect that is the key difference to message. |
It's definitely a new way of thinking. In ZF2 customization was actually really hard. You had to understand the various events to be able to add your own code before the controller, or after, which ended with a very complex workflow. In Expressive, I actually don't use event manager (it's not even part of my dependencies): the workflow is explicitly defined by the middleware piping and definitely makes things sooooo much easier to understand that I actually find Expressive much more suited for bigger apps or complex apps. Need a custom authentication mechanism for some endpoints? Just add a middleware only for those paths. After trying Expressive I'm having a hard time finding where the Zend\Mvc can be superior. It is less flexible, less performant, harder to follow. For me the only reason to use Zend\Mvc (and, therefore, the eco-system around it) is the facilities provided by the module eco-systems. But even in that case, I've found out that for that, the middleware philosophy makes it so much easier. You no longer need to install Zend\Authentication that would try to map into the mvc, spending a lot of time how it works... Want an authentication? Just analyze your need, and boom, ten lines letter, it's done: class AuthenticationMiddleware
{
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out)
{
$token = $request->getHeaderLine('Authorization');
if (empty($token)) {
return $response->withStatusCode(401);
}
try {
$user = $this->userService->getByToken($token);
} catch (NotFoundException $exception) {
return $response->withStatusCode(401);
}
$request = $request->withAttribute('logged_user', $user->getId());
return $out($request, $response);
}
} |
@bakura10 It's cool and very deep answer given by the @weierophinney . Thanks a lot guys and keep updating this talk. 👍 |
Thank you for this discussion! I am currently starting my first Expressive application, which should be REST API for a mobile app + admin application, used from a couple of different user roles to add/change data, send push notifications to mobile app users etc. I am currently considering to develop both the API and the admin application with Expressive, using the possibility for path segregation and different middleware pipe for different paths (/admin and /api). I would like to reuse doctrine entities, repositories and services in the admin application and in the REST API. Another idea I have is to make the admin application with ZF2, which we have used for a couple of other similar applications, with Doctrine and modules like ZfcUser and ZfcRbac. And then reuse the entities, repositories and services from the ZF2 application and make the REST API with Expressive, which is more suitable for this purpose. @mtymek you mention you have used Expressive on top of ZF1 application. Could you please share how did you connect them and reused the ZF1 code in Expressive? @weierophinney @xtreamwayz @bakura10 could you please share opinions what architecture is better for this use case and is the combination of Expressive for REST API + ZF2 for application logic possible? |
You can use piping to run different applications based on paths. $app = AppFactory::create();
$app->pipe('/blog', new WordPressMiddleware());
$app->pipe('/api', new ExpressiveApiMiddleware());
$app->pipe('/admin', new ZF2AdminMiddleware());
$app->pipe('/store', new MagentoMiddleware());
$app->run(); And inside those middleware you start the application. In theory you can share the container between your different apps, especially with Expressive and ZF2. To reuse entities I create a Domain namespace (sort of module). It contains only the entities and repositories. I can then reuse those between other modules. But if you share the zf2 and expressive config in the same container you can probably access those anyway without moving them into a Domain module (disclaimer: I haven't tried this yet). |
My idea was to setup up Expressive "before" ZF1 app. If Expressive is not able to route the request, it is then passed to underlying ZF1 code. This allowed us to benefit from PSR-7 for new parts of the platform, without rewriting any of the legacy ZF1 codebase. Initially I wanted covert PSR-7 request into
Because of the above, I ended up with a bit "hacky" code. I created my own wrapper around public function run()
{
$this->expressiveApp->pipe('/', [$this, 'zf1AppMiddleware']);
// ...
} My middleware simply bootstraps and runs legacy application: public function zf1AppMiddleware(ServerRequestInterface $request, ResponseInterface $response)
{
$application = new Zend_Application(
APPLICATION_ENV,
$this->container->get('config')
);
$zf1App->bootstrap();
$zf1App->run();
return new Zf1Response();
}
$request = ServerRequestFactory::fromGlobals();
$app = $this->expressiveApp;
$response = $app($request, new Response());
if ($response instanceof Zf1Response) {
// ZF1 app - output is already sent
return;
}
$emitter = new SapiEmitter();
$emitter->emit($response); It is more or less how it works. I didn't have to worry about reusing code written for ZF1 in Expressive parts, because we've been already using |
@xtreamwayz @mtymek Thank you for the ideas and the useful feedback! It's interesting approach to mix applications in this way. I will probably try it with ZF2 and Expressive later, if some of our existing ZF2 projects needs an API. For my new project I decided to stay with Expressive both for API and admin web app. The things I miss the most are the ZfcUser and ZfcRbac modules, which are currently tightly coupled with ZF2 MVC. But middleware allows simpler implementation of authentication and authorization according to specific project requirements and I start liking Expressive more and more as long as work with it and get used to it. |
After creating a couple of projects with Zend\Expressive, my default preference is to choose Expressive for any new project — if the choice is mine that is. The reason for that, others here have already expressed quite eloquently. However, for completeness, I'll clarify what I mean. Zend\MVC has, as @weierophinney says, a set of preconceptions about how things are done, yet they're very broad and unspecific. It also has a number of pre-wired structures in place. This requires you to know a lot of what those things are — if you really want to use it optimally. To quote Matthew:
Zend\Expressive (I'm referring to apps based on the Expressive Skeleton Installer) on the other hand, comes with barely any of these assumptions and requirements. It provides a very minimalist structure, essentially a:
Given that, you can very quickly get up to speed with creating exactly the app that you need. I’d argue very strongly that this approach, in contrast to the Zend\Mvc approach, is the more flexible and accommodating. What’s more, you can mix and match the types of applications that you create. Just need an API, great, you can do that quite quickly. Want an HTML-based front-end, that’s available too. You can make use of any other Zend library, or non-Zend library. The buffet of choice and the flexibility provided is tantalising. Given that, I’m not saying that Zend\Mvc is bad! What I am saying is that:
|
@settermjd I like how succinctly you've written this; would you be willing to write it up to include in both the zend-expressive and zend-mvc documentation, by any chance? |
Sure can. It'll be done by week's end. |
After participating in the discussion on [When to choose Zend\Expressive over Zend\Mvc](zendframework#283), issue zendframework#283, @weierophinney asked me to take what I'd written and add it to the Zend\Expressive and Zend\Mvc docs. This commit adds said revised version of my feedback, to the docs.
Zend Expressive designed it not to be able to use in a project different frameworks and/or libraries that support the standard PSR-7? For example, routes requests "example.com/api/v1" or "/gallery" I want to treated Zend components, but routes "example.com/newscompany" Symfony or Phalcon. I also think that Zend Expressive is well suited for Microservice Architecture? Zend Expressive (PSR-7) is there any way to stop the dispute is best to choose a framework for development and focus on the development (code) programming PHP language. |
Expressive is a framework. It's the middleware that is/are designed to be reused. Interestingly, a
TBH, I'd rather set that up at gateway level, but yeah, it can be done with expressive too.
The word "microservice" is inflated. You can build a microservice even with the largest J2EE installation: the point is keeping the API surface minimal. The code amount is not really important.
This is a never-ending discussion, and TBH, it's good to keep having it. Without this sort of discussion, framework development would stall, and we would be back in the age of "one framework for everything", which has both advantages and disadvantages. |
@Ocramius Thank you for your comments.
Can any example, please? I do not quite understand what it was about. |
Before hitting PHP. Can be done in a load balancer or equivalent. |
About what @xtreamwayz said
I tried to do that with apigility in expressive but the major problem is that apigility use and injects in ResourceFactory another instance of ServiceManager than the container used by Expressive and probably the same will happen in Zend-MVC . Also Expressive allow you to add services using 'dependencies' key and in Zend-MVC 'service_manager' key . I thought that one possibility is to merge both configs once in Expressive and once in Apigility when the general config is created but I don't really like to have to load and use two containers so how can I tell in Apigility(Zend-MVC) to use as container( $services ) the Expressive container? |
Thank you for your information. Bought @RalfEggert s Book on ZF3 (in German) and red a little about Zend Expressive. For a small project (collection of "people" lets say, artists, with single-artist pages, overviews and upload-forms -databased) including the ambition to learn more about ZF, we started with MVC and I am now considering switching to Zend Expressive. A question which probably shows that I am not yet deep into this: does Zend\Form Zend\Filter (I managed to create a file-upload-form with Zend\MVC) work the same way with Zend Expressive or is there a "wiring behind the curtains" in MVC which Expressive does not have (asking may-be @weierophinney too). Thanks for your eventual replies. Frank Ix - aka Robert Sauer-Ernst |
I can't help you there as I don't use zend-form myself.
Besides that this issue is already closed and you are sort of hijacking it with something not related to it, we have a forum and slack for questions. |
@xtreamwayz - Thanks and sorry. Do not want to be a hijacker ;-). Did not see it was closed. Thanks. |
@frankx zend-filter, zend-validator, zend-inputfilter, zend-hydrator, and zend-form all expose themselves as config providers. What this means is that if you use the Expressive skeleton to start your app, and then add any of these packages, you will be prompted to inject their config providers in your That said, be aware that we only provide view helpers for zend-view, so you'll either need to use zend-view as your template engine, or write your own helpers for the template engine of your choice. |
@weierophinney Thank you for this precise answer! |
In the "Announcing the Zend Framework 3 Roadmap" blog entry, someone asked an interesting question which probably will be asked by many others.
http://framework.zend.com/blog/announcing-the-zend-framework-3-roadmap.html#comment-2476333814
I will reask here: When should someone choose Zend\Expressive and when Zend\Mvc?
Any ideas?
I will be glad to sum it up for the docs. Maybe could be added to the Zend\Mvc docs as well
The text was updated successfully, but these errors were encountered: