Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial approach #1

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
vendor
composer.lock
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,61 @@
# Zend-Expressive-Bridge
# Zend-Expressive-Bridge

The easiest way to use PHP-DI with Zend Expressive, seems to:

- use the Dependency Injection Container Builder provided by this library using some default definition files
- add your own Dependency Definitions to the Container Builder
- use the Dependency Injection Container to fetch the Zend Expressive Application
- run the Application

## In your ```./public/index.php```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline code blocks are made with single quotes: "In your ./public/index.php"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, did not know that...


```php

<?php
// Delegate static file requests back to the PHP built-in WebServer
if (php_sapi_name() === 'cli-server'
&& is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))
) {
return false;
}

require __DIR__ . '/../vendor/autoload.php';

/* @var \Interop\Container\ContainerInterface $container */
$container = require __DIR__ . '/../config/container.php';

/* @var \Zend\Expressive\Application $app */
$app = $container->get(\Zend\Expressive\Application::class);
$app->run();

```

## In your ```./config/container.php```


```php
<?php
/* @var \DI\ContainerBuilder $containerBuilder */
$containerBuilder = require __DIR__ . '/../vendor/php-di/zend-expressive-bridge/config/containerBuilder.php';
$inProduction = false; //You probably want to use an environment variable for this...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an idea: instead of requiring the containerBuilder.php file that is in vendor/ there could be instead a class, e.g. ExpressiveContainerBuilder, that extends from ContainerBuilder and auto-add the configuration files of this repository.

The advantage I see is it benefits from autoloading so it avoids the long line of include that goes looking in vendor/ (which is kind of unusual), and also the possibility to get rid of all the if(class_exists('Zend\Expressive\Router\AuraRouter')){ in the config files => the ExpressiveContainerBuilder could have methods dedicated to include configuration for libraries.

Here is an example of what it could look like:

// the $inProduction could be used to enable/disable Twig debug or other debug for example
$containerBuilder = new ExpressiveContainerBuilder($inProduction);
$containerBuilder->registerAuraRouter();
$containerBuilder->registerTwigRenderer();
// All methods of the container builder can still be used of course
$containerBuilder->addDefinitions(/* your own definition files */);

It's a bit less automatic than your current solution but relying on class_exists is risky IMO, it's not because a class is installed in vendor/ that you want to use it in your application. And that way it's much more explicit/easier to understand what's happening.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm, seems better indeed, will have a look at this!

$containerBuilder->writeProxiesToFile($inProduction, __DIR__ . '/../data/cache'); //You probably want to use caching in production

/**
* Add your own, application-specific, Dependency Definitions to the Container Builder
* @link https://zend-expressive.readthedocs.io/en/latest/features/modular-applications/
*/
$pathToDependencyDefinitions = __DIR__ . '/../config/dependencies/{{,*.}global,{,*.}local}.php';
$phpFileProvider = new \Zend\ConfigAggregator\PhpFileProvider($pathToDependencyDefinitions);
$dependencyDefinitions = $phpFileProvider();
foreach ($dependencyDefinitions as $definitions) {
$containerBuilder->addDefinitions($definitions);
}

$container = $containerBuilder->build();

//Assign configuration to container
$config = require __DIR__ . '/../config.php';
$container->set('config', $config);

return $container;
```
22 changes: 22 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "php-di/zend-expressive-bridge",
"description": "PHP-DI integration in Zend Expressive",
"license": "MIT",
"type": "library",
"require": {
"php": "@stable",
"php-di/php-di": "@stable",
"php-di/invoker": "@stable",
"zendframework/zend-expressive": "@stable",
"zendframework/zend-expressive-helpers": "@stable"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to restrict to major versions to avoid being affected by a BC break in any of those packages.

Random example: the class Zend\Expressive\Container\ApplicationFactory could very well be removed in a new major version.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

},
"suggest": {
"zendframework/zend-config-aggregator": "To easily add application specific Dependency Definitions to the ContainerBuilder",
"zendframework/zend-expressive-aurarouter": "To route requests using Aura.Router",
"zendframework/zend-expressive-fastroute": "To route requests using FastRoute",
"zendframework/zend-expressive-zendrouter": "To route requests using zend-mvc Router",
"zendframework/zend-expressive-platesrenderer": "To use Plates as templating engine",
"zendframework/zend-expressive-twigrenderer": "To use Twig as templating engine",
"zendframework/zend-expressive-zendviewrenderer": "To use zend-view PhpRenderer as templating engine"
}
}
12 changes: 12 additions & 0 deletions config/autoload/dependencies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
declare(strict_types = 1);

return array(
\Interop\Container\ContainerInterface::class => function (\Interop\Container\ContainerInterface $container) {
return $container;
},
\Zend\Expressive\Application::class => \DI\factory(\Zend\Expressive\Container\ApplicationFactory::class),
\Zend\Expressive\Container\ApplicationFactory::class => \DI\object(),
\Zend\Expressive\Helper\ServerUrlHelper::class => \DI\object(),
\Zend\Expressive\Helper\UrlHelper::class => \DI\factory(\Zend\Expressive\Helper\UrlHelperFactory::class),
);
22 changes: 22 additions & 0 deletions config/autoload/dependencies.router.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php
declare(strict_types = 1);

if(class_exists('Zend\Expressive\Router\AuraRouter')){
return array(
\Zend\Expressive\Router\RouterInterface::class => \DI\get(\Zend\Expressive\Router\AuraRouter::class),
\Zend\Expressive\Router\AuraRouter::class => \DI\object(),
);
}
if(class_exists('Zend\Expressive\Router\FastRouteRouter')){
return array(
\Zend\Expressive\Router\RouterInterface::class => \DI\get(\Zend\Expressive\Router\FastRouteRouter::class),
\Zend\Expressive\Router\FastRouteRouter::class => \DI\object(),
);
}
if(class_exists('Zend\Expressive\Router\ZendRouter')){
return array(
\Zend\Expressive\Router\RouterInterface::class => \DI\get(\Zend\Expressive\Router\ZendRouter::class),
\Zend\Expressive\Router\ZendRouter::class => \DI\object(),
);
}
throw new RuntimeException('No Router available to use in Dependency Injection Container');
27 changes: 27 additions & 0 deletions config/autoload/dependencies.templating.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php
declare(strict_types = 1);

if(class_exists('Zend\Expressive\Plates\PlatesRendererFactory')){
return array(
\Zend\Expressive\Template\TemplateRendererInterface::class => \DI\factory(\Zend\Expressive\Plates\PlatesRendererFactory::class),
);
}
if(class_exists('Zend\Expressive\Twig\TwigRendererFactory')){
return array(
\Zend\Expressive\Template\TemplateRendererInterface::class => \DI\factory(\Zend\Expressive\Twig\TwigRendererFactory::class),
);
}
if(class_exists('Zend\Expressive\ZendView\ZendViewRendererFactory')){
return array(
\Zend\Expressive\Template\TemplateRendererInterface::class => \DI\factory(\Zend\Expressive\ZendView\ZendViewRendererFactory::class),
/**
* injectHelpers() seems to use an incorrect 'default' HelperPluginManager resulting in:
* Deprecated: Zend\ServiceManager\AbstractPluginManager::__construct now expects a Interop\Container\ContainerInterface instance representing the parent container; please update your code in
*
* @see \Zend\Expressive\ZendView\ZendViewRendererFactory::injectHelpers()
*/
\Zend\View\HelperPluginManager::class => \DI\factory(\Zend\Expressive\ZendView\HelperPluginManagerFactory::class),
);
}

return array(); //Template engine is not mandatory
12 changes: 12 additions & 0 deletions config/autoload/errorHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
declare(strict_types = 1);

return array(
\Zend\Expressive\Container\WhoopsErrorHandlerFactory::class => \DI\object()->lazy(),
\Zend\Expressive\Container\WhoopsFactory::class => \DI\object()->lazy(),
\Zend\Expressive\Container\WhoopsPageHandlerFactory::class => \DI\object()->lazy(),
'Zend\Expressive\Whoops' => \DI\factory(\Zend\Expressive\Container\WhoopsFactory::class),
'Zend\Expressive\WhoopsPageHandler' => \DI\factory(\Zend\Expressive\Container\WhoopsPageHandlerFactory::class),
'Zend\Expressive\FinalHandler' => \DI\factory(\Zend\Expressive\Container\WhoopsErrorHandlerFactory::class),
//'Zend\Expressive\FinalHandler' => \DI\factory(\Zend\Expressive\Container\TemplatedErrorHandlerFactory::class), //In production
);
8 changes: 8 additions & 0 deletions config/autoload/middleware-pipeline.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

declare(strict_types = 1);

return array(
\Zend\Expressive\Helper\ServerUrlMiddleware::class => \DI\factory(\Zend\Expressive\Helper\ServerUrlMiddlewareFactory::class),
\Zend\Expressive\Helper\UrlHelperMiddleware::class => \DI\factory(\Zend\Expressive\Helper\UrlHelperMiddlewareFactory::class),
);
9 changes: 9 additions & 0 deletions config/containerBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);

return (new \DI\ContainerBuilder())
->addDefinitions(__DIR__ . '/autoload/dependencies.php')
->addDefinitions(__DIR__ . '/autoload/dependencies.router.php')
->addDefinitions(__DIR__ . '/autoload/dependencies.templating.php')
->addDefinitions(__DIR__ . '/autoload/errorHandler.php')
->addDefinitions(__DIR__ . '/autoload/middleware-pipeline.php');