Doctrine Orm Tools via Zend Framework - php

In order to use the Doctrine Module ORM tools for a Zend 2 project, I need to run the command via Zend so that the bootstrapping options defined in index.php and application.config.php are correctly established.
The sum off these definitions enable a config file to be loaded which contains DB settings I wish to inject into Doctrine. This is achieved via a custom DBALConnectionFactory.
The doctrine configuration in my application.config.php is like this:
'doctrine' => array(
'entity_path' => array (
__DIR__ . '../src/Application/Entity'
),
'driver' => array(
'ApplicationDriver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/Application/Entity')
),
'orm_default' => array(
'drivers' => array(
'Application\Entity' => 'ApplicationDriver'
)
)
),
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'DoctrineTypeMappings' => array(
'enum' => "string"
)
)
)
),
'doctrine_factories' => array(
'connection' => 'Application\ORM\DBALConnectionFactory',
),
According to Sam in how to configure doctrine command line tools on zenframework 2, I should be able to use
php public/index.php orm:schema-tool:create
but all that does for me is to lists the commands available (that suggests that the parameters are not being mapped correctly).
I have also tried (from the project root) the following commands to no avail:
php public/index.php doctrine orm:schema-tool:create
php public/index.php doctrine orm orm:schema-tool:create
Has anyone had any luck using the Doctrine Tools via Zend? All responses gratefully received!

The issue was caused by a custom console route interfering with the parameters for the standard route. I have amended it to pass all requests made via public/index.php straight to the standard router.
public function match(Request $request)
{
// Get command line arguments and present working directory from
// server superglobal:
$filename = $request->getScriptName();
if ("public/index.php" === $filename) {
return parent::match($request);
}
// WARNING: cwd is $APPLICATION_HOME, so that throws off realpath!
//
// Convert base filename (minus .php extension and underscores) and
// containing directory name into action and controller, respectively:
$base = basename($filename, ".php");
$actionName = str_replace('_', '', $base);
$dir = dirname($filename);
//invoked in directory e.g. $base=util/ping.php
$level1 = basename(dirname($filename));
// re-orient relative to APPLICATION_HOME
$path = $level1 . '/' . basename($filename);
$controller = basename($dir);
$routeMatch = new RouteMatch(
array('controller' => $controller, 'action' => $actionName), 1
);
// Override standard routing:
$routeMatch->setMatchedRouteName('default');
return $routeMatch;
}

Related

ZF2 Routes - The requested URL could not be matched by routing

I'm having trouble setting up a route for a very simple controller. I'm getting the "The requested URL could not be matched by routing." error. I've viewed similar solved questions on SO and can't pinpoint what I'm doing wrong (Ex: ZF2 - Zend Framework 2, understanding routing)
I've followed the skeleton tutorial with the albums subject and everything functioned perfectly fine. I tried duplicating the album module and then changing the name of the controller, folder, module config, etc. I figured this would be a good way to confirm I can at least replicate working code. I'm just trying to echo "123" to the page, so I tried eliminating the directories for forms, models and some of the views from the new module.
Is there some way to see what route I'm really looking for and what routes I defined? I know CI actually created a log file I was able to check. It was kind of like Apache logs but specific to framework functionality.
I'd like to post some of my code so someone could point out the mistake I am making and possibly explain why it is wrong. I tried paying close attention to case since different variations of the word album are used throughout the tutorial and I'm not 100% sure which ones are supposed to match up with what just yet. I'm trying to make it work for http://www.example.com/productbriefs.
Folder Structure
module.config.php:
return array(
'controllers' => array(
'invokables' => array(
'Productbriefs\Controller\Productbriefs' => 'Productbriefs\Controller\ProductbriefsController',
),
),
// The following section is new and should be added to your file
'router' => array(
'routes' => array(
'productbriefs' => array(
'type' => 'Literal',
'options' => array(
'route' => '/productbriefs',
'defaults' => array(
'controller' => 'Productbriefs\Controller\Productbriefs',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'productbriefs' => __DIR__ . '/../view',
),
),
);
ProductbriefsController.php
namespace Productbriefs\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class ProductbriefsController extends AbstractActionController
{
public function indexAction()
{
echo "123";
}
}
Module.php
namespace Productbriefs;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module implements AutoloaderProviderInterface, ConfigProviderInterface
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
// Add this method:
public function getServiceConfig()
{
return array(
'factories' => array(),
);
}
}
As per my comment, you need to add Productbriefs to the module array in application.config.php or the module (including its configuration) will not be loaded.
To answer your second question, the controller manager needs to know how to load the controller classes your application uses. An 'invokable' is a class that can be instantiated without needing any arguments passed to it, so by adding controllers to that array you're telling the controller manager that it can instantiate that class simply by doing $controller = new Productbriefs\Controller\ProductbriefsController(). The key for the array is an alias, yes. This can be anything, although the ZF convention is to use the fully qualified name of the class but omit the 'Controller' suffix from the end. When you refer to controllers in your routing config you use these aliases.

Module (album) could not be initialized zf2 tutorial

I am working through the zend framework 2 tutorial application. I have set up my Album Module directory as follows:
I am running into an error when I start my MAMP server, Fatal error: Uncaught exception 'Zend\ModuleManager\Exception\RuntimeException' with message 'Module (Album) could not be initialized.'
If I comment out the Album module from the following code (in /config/application.config.php):
'modules' => array(
'Application',
'Album',
),
I get to the skeleton application homepage.
Here is my /module/Album/Module.php code:
namespace Album;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
class Module implements AutoloaderProviderInterface, ConfigProviderInterface {
public function getAutoloaderConfig() {
return array(
’Zend\Loader\ClassMapAutoloader’ => array(
__DIR__ . ’/autoload_classmap.php’,
),
’Zend\Loader\StandardAutoloader’ => array( ’namespaces’ => array(
__NAMESPACE__ => __DIR__ . ’/src/’ . __NAMESPACE__,
),
),
);
}
public function getConfig() {
return include __DIR__ . ’/config/module.config.php’;
}
public function getServiceConfig() {
return array(
’factories’ => array(
’Album\Model\AlbumTable’ => function($sm) {
$tableGateway = $sm->get(’AlbumTableGateway’);
$table = new AlbumTable($tableGateway);
return $table;
},
’AlbumTableGateway’ => function ($sm) {
$dbAdapter = $sm->get(’Zend\Db\Adapter\Adapter’);
$resultSetPrototype = new ResultSet(); $resultSetPrototype->setArrayObjectPrototype(new Album());
return new TableGateway(’album’, $dbAdapter, null, $resultSetPrototype);
},
),
);
}
}
And here is my module.config.php code in /module/Album/config/:
return array(
’controllers’ => array(
’invokables’ => array(
’Album\Controller\Album’ => ’Album\Controller\AlbumController’,
),
),
’view_manager’ => array(
’template_path_stack’ => array(
’album’ => __DIR__ . ’/../view’,
),
),
'router' => array(
'routes' => array(
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
),
),'
);
I have read through a few people who have ran in to similar situations, but their issues were due to misspelled/incorrectly named classes. I don't see anything wrong with my code (even went as far as copying/pasting directly from tutorial).
Can someone give me some suggestions?
Thanks
I had the same problem, and the solution was to start every .php file with <?php
This is not clear in the tutorial (if you just copy the code from there), and it was the reason I was getting the same exception.
The only reason i could see is that you should replace all ’ with normal single quotes '.
using ’ can results in unexpected behaviors.
There is an error in the tutorials module.config.php file.
Change 'id' => '[0-9]+',
to 'id' => '[0-9]*',
+ means one or more digits. If you just call http://zf2-tutorial.localhost/album/ there is no digit in the url so the rewriterule doesn't match. Change from + to * (0 or more)
I had the exact same issue, my issue and solution were
the very first command in the tutorial is:
php composer.phar create-project --stability="dev" zendframework/skeleton-application path/to/install
It was cut off my screen so I copy/pasted the command to the command line without reading the end. So my app directory structure included a directory ./path/to/install where all of the installation files were, including application.config.php.
Moving everything in /path/to/install/ to the root directory of the app allowed Zend to find the Album module.
Note: /path/to/install/module contains the album module but will fail if you do
mv ./path/to/install/* .
so be sure to move the Application module at /path/to/install/module into app_root_dir/module/.
You can check composer.json weather include the following:
"autoload": {
"psr-4": {
"Application\\": "module/Application/src/",
"Album\\": "module/Album/src"
}
},
Please check your Module::getConfig() ,
and play with :
return include __DIR__ . '/../config/module.config.php';
I have added '../' prefix and it works well .

ZendFramework 2 - how can i do the similar Bootstrap.php like in ZF1?

I have ZF 1 where i got working Bootstrap.php with lots of routing and other preDispatch stuff.
But in ZF2 there is no Bootstrap.php concept anymore? Or i mean how can i do this same in Zf2?
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initPdispatch() {
$this->bootstrap('frontController');
require_once APPLICATION_PATH . '/controllers/plugin/LanguageSelector.php';
$plugin = new LanguageSelector();
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin($plugin);
return $plugin;
}
protected function _initRoutes() {
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$dynamic1 = new Zend_Controller_Router_Route(
'/:variable1',
array(
'controller' => 'router',
),
// array('variable1' => '^[a-zA-Z0-9_-]*$')
array('variable1' => '^[\w.-]*$')
);
$router->addRoute('dynamic1', $dynamic1);
}
One of the best features of ZF2 is something that I actually hated at first, which are the routes. It's both great and annoying because now you're required to set the routes for all of your modules.
Part of understanding ZF2 (more quickly) is understanding modules. If you can get past this, you will begin to adapt much more quickly. (At least that's how it was for me). So, what in ZF2 is a module? Anything!
Anyway, all of the config files for every module and for the application eventually get merged within the Zend Framework, so that means you can define routes anywhere really.
That said, you don't need to "bootstrap" your routes anymore as that is part of your ModuleName/config/module.config.php file. now.
Now, I'm not an expert on regex routes within ZF2, but it would be something like:
// MyModule/config/module.config.php
return array(
'router' => array(
'routes' => array(
'dynamic1' => array(
'type' => 'regex',
'options' => array(
'route' => '/[:variable1]'
)
)
)
)
);
Somewhere in there you define the regex. Additionally, I saw in their docs that you can also define a regex route manually:
use Zend\Mvc\Router\Http\Regex;
// ...
$route = Regex::factory(array(
'regex' => '/blog/(?<id>[a-zA-Z0-9_-]+)(\.(?<format>(json|html|xml|rss)))?',
'defaults' => array(
'controller' => 'Application\Controller\BlogController',
'action' => 'view',
'format' => 'html',
),
'spec' => '/blog/%id%.%format%',
));
$router->addRoute($route);
You should be able to add this as a service or put it in onBootstrap() within the Application module if you're using the Skeleton Application.
Keep in mind, that was their example and again, I'm not an expert on this. Here is some more information.
Hope this helps!

How to use Memcached in Doctrine2 / ZF2?

I have set up my code / directories / configuration as outlined in this article: http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/
So my config file looks something like:
<?php
namespace Game;
return array(
// <snip>
// Doctrine config
'doctrine' => array(
'driver' => array(
__NAMESPACE__ . '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity')
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
)
)
)
),
);
Now, what do I need to set/change to make Doctrine use Memcached as its caching backend? I have searched a lot on Google, but other than in this question, where it says they got it working (but not how), I have not been able to find anything.
They had posted the official way to support it here
forget the previous answer. after spending hours tracing the errors i found that doctrine looks for "doctrine.cache.instance" the value there should be a string referencing the service you set up in the service manager.
however, due to a bug in the doctrine code base the config is never retrieved. i will submit this to github later.
but the good news is that when no "doctrine.cache.instance" is given the alias "my_memcached_alias" is used.
so the above code can easely be fixed and the awkward hacks removed from the doctrine source.
(note: i left the doctrine.cache config in for future compatibility and showing the proper way to set the instance alias)
module.config.php
'doctrine' => array(
'driver' => array(
__NAMESPACE__ . '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'memcached',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity'),
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver',
),
),
),
'cache' => array(
'instance' => 'my_memcached_alias',
),
),
'service_manager' => array(
'factories' => array(
'my_memcached_alias' => function() {
$memcached = new \Memcached();
$memcached->addServer('localhost', 11211);
return $memcached;
},
),
),
i hope you have already found a solution by now that doesnt involve a framework modification, but for al the people still searching for answers this will definetly help
Edit:
After Many headaches I found out that th config should be doctrine.cache.memcache.instance
second edit:
here's the correct code
'cache' => array(
'memcache' => array(
'instance' => 'memcacheService',
),
),
I had some trouble to get it working and I only have a temporary workaround as I needed to modify the Doctrine ORM Module itself.
First, set the cache to memcache: 'cache' => 'array', to 'cache' => 'memcache', in your config above.
Then, define a service factory to create the memcache instance. You can do this in a module class:
NOTE: This example bases on memcache, not memcacheD. But it should be the same for memcached.
function getServiceConfig()
{
return array(
'factories' => array(
'memcache' => function(ServiceManager $sm) {
$memcache = new \Memcache(); // .. do some configuration and connect
return $memcache;
}
)
);
}
The last step is to modify the Doctrine ORM Module. Otherwise, it won't create the instance and throws an error.
In DoctrineModule/Service/CacheFactory.php l61 :
$cache->setMemcache($options->getInstance());
Becomes:
$cache->setMemcache($sl->get($options->getInstance()));
(In your case, do this for line 64.) Or find another way to inject a memcached instance into $options. Be aware that this should only be a workaround and be fixed as soon as possible. Otherwise, you'll have trouble updating the module.
Hope this helps.
We don't need to change core Doctrine ORM module source.
Change factories to:
return array(
'factories' => array(
'my_memcache_alias' => function(ServiceManager $sm) {
$memcache = new \Memcache(); // .. do some configuration and connect
return $memcache;
}
)
);
First of all install the memcached php extension.
~ # > aptitude install php5-memcached
After that you will need to configure the memcached servers parameters
//app/config/parameters.yml
parameters:
...
memcache_hosts:
-
dsn: 127.0.0.1
port: 11211
Next we need to create some services
services:
memcached:
class: Memcached
calls:
- [ addServers, [%memcache_hosts%] ]
doctrine.cache.memcached:
class: Doctrine\Common\Cache\MemcachedCache
calls:
- [ setMemcached, [ #memcached ] ]
After that we will need to add some configuration to config.yml
//app/config/config.yml
...
doctrine:
...
orm:
entity_managers:
default:
...
metadata_cache_driver:
type: service
id: doctrine.cache.memcached
query_cache_driver:
type: service
id: doctrine.cache.memcached
result_cache_driver:
type: service
id: doctrine.cache.memcached
Now We can use Memcached to cache our queries as the Doctrine Doc explains.
Also we have three symfony commands to clear the doctrine cache
$> php app/console doctrine:cache:clear-metadata
//Clears all metadata cache for an entity manager
$> php app/console doctrine:cache:clear-query
//Clears all query cache for an entity manager
$> doctrine:cache:clear-result
//Clears result cache for an entity manager
I have extracted these steps from:
https://blog.42mate.com/implementing-doctrine-caching-with-memcached-in-symfony-2/

addResourceType - how can I add Models_Mapper as a resource?

I'm writing a PHP application using
PHP 5.3 and Zend Framework 1.11.7.
I created model resource using the following command:
protected function _initLoader()
{
$loader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Default',
'basePath' => APPLICATION_PATH,
));
$loader -> addResourceType ( 'model', 'models', 'Model');
}
now whenever i use a class name that starts with Default_Model_ it goes and searches in models directory. under models directory i have a directory called mapper.
how can I configure that whenever a class is being used that starts with Default_Model_Mapper_ to auto-load it from models/mapper ?
ZF should find any directory under models automatically. Also you shouldn't need to include the default module either.
Model_
Model_Mapper_
Also to setup ZF modules I have the following 2 lines of code in my application.ini file
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] =
And the following in my bootstrap
protected function _initModuleAutoload()
{
$modelLoader = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH . '/modules/default'));
return $modelLoader;
}
I hope this is of some help
Kind regards
Garry
Add this one:
$loader->addResourceType('mapper', 'models/mapper', 'Model_Mapper_');
The order in which you declare the two resource types might matter. So try it both ways; one of them should work.
It is set by default in Zend_Application_Module_Autoloader in initDefaultResourceTypes:
$this->addResourceTypes(array(
'dbtable' => array(
'namespace' => 'Model_DbTable',
'path' => 'models/DbTable',
),
'mappers' => array(
'namespace' => 'Model_Mapper',
'path' => 'models/mappers',
),
'form' => array(
'namespace' => 'Form',
'path' => 'forms',
),
....

Categories