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/
Related
I am trying to install ScnSocialAuth_ZendSessionManager into my zend 2 application.
i am getting the following error message when i try to go to the login or registration page:
An alias "ScnSocialAuth_ZendSessionManager" was requested but no service could be found.
i have followed the instructions here:
and uploaded it.
i then install
./vendor/socalnick/scn-social-auth/config/scn-social-auth.global.php.dist
/vendor/socalnick/scn-social-auth/config/scn-social-auth.local.php.dist
to my config.
Then within the scn-social-auth.global.php i did the following:
$settings = array(
'zend_db_adapter' => 'Zend\Db\Adapter\Adapter',
'zend_session_manager' => 'Zend\Session\SessionManager'
}
);
return array(
'scn-social-auth' => $settings,
'service_manager' => array(
'aliases' => array(
'ScnSocialAuth_ZendDbAdapter' => (isset($settings['zend_db_adapter'])) ? $settings['zend_db_adapter']: 'Zend\Db\Adapter\Adapter',
'ScnSocialAuth_ZendSessionManager' => (isset($settings['zend_session_manager'])) ? $settings['zend_session_manager']: 'Zend\Session\SessionManager',
),
),
);
i also created a ./config/autoload/session.local.php:
<?php
return array(
'service_manager' => array(
'invokables' => array(
'Zend\Session\SessionManager' => 'Zend\Session\SessionManager',
),
),
);
so, i am unclear why i am still getting the error message;
would really appriciate any advise on this.
UPDATE
i also added the module to composer:
"require": {
"php": ">=5.3.3",
"zendframework/zendframework": "2.*",
"socalnick/scn-social-auth": "1.*"
}
UPATE
Wilt has asked what values are returned when i var_dump the config values.
the returned values are:
array (size=3)
'ScnSocialAuth_ZendDbAdapter' => string 'Zend\Db\Adapter\Adapter' (length=23)
'ScnSocialAuth_ZendSessionManager' => string 'Zend\Session\SessionManager' (length=27)
'zfcuser_zend_db_adapter' => string 'Zend\Db\Adapter\Adapter' (length=23)
you will observe that the ScnSocialAuth_ZendSessionManager is aliasing the zend sesssion manager.
so, i am unclear why it say that the service cannot be found.
would really appriciate some advice on this.
You need the scn-social-auth.global.php and the scn-social-auth.local.php to you application config folder and set all the config parameters that are required.
In this file you find the key 'ScnSocialAuth_ZendSessionManager'. Your issue is probably related to some configuration problem related to these config files.
Since you said you loaded them I would says something is wrong with your autoload setup.
Does your ZF2 application have the proper system configuration:
'module_listener_options' => array(
'module_paths' => array(
'./module',
'./vendor',
),
'config_glob_paths' => array(
'config/autoload/{{,*.}global,{,*.}local}.php',
)
)
Check once if your merged $config array contains all your keys?
$config = $serviceManager->get('Config');
I stuck with the $defaultLocale of the TranslatableListener.
https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/translatable.md#default-locale
I found only setup possibilities for Symphony, but not for Zend Framework 2.
There is an extension bundle for doctrine for easy setup of DoctrineExtensions named "StofDoctrineExtensionsBundle", but I didn't found something like that for ZF2.
The following link shows a best practices for setting up translatable and other DoctrineExtensions, but where should I put it and isn't there an easier approach?
https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/annotations.md#best-practices-for-setting-up-with-annotations
I only want to know how I can configure the $defaultLocale of the TranslatableListener in a ZF2 environment.
UPDATE:
I tried in my bootstrap the following:
$translatableListener = new TranslatableListener();
$translatableListener->setDefaultLocale('de-DE');
$doctrineEventManager->addEventSubscriber($translatableListener);
But still getting:
.../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/TranslatableListener.php:464 Gedmo\Translatable\Mapping\Event\Adapter\ORM->loadTranslations
$object Rental\Entity\Rental
$translationClass "Rental\Entity\RentalTranslation"
$locale "en_US"
$objectClass "Rental\Entity\Rental"
So my mistake was, that I configured the TranslatableListener twice.
In my doctrine configuration (only for explanation there is a comment before, delete the whole line):
'doctrine' => [
'eventmanager' => [
'orm_default' => [
'subscribers' => [
'Gedmo\Timestampable\TimestampableListener',
'Gedmo\Sluggable\SluggableListener',
// 'Gedmo\Translatable\TranslatableListener',
],
],
],
and in bootstrap:
// sets the default locale and the actual locale
$translatableListener = new TranslatableListener();
$translatableListener->setDefaultLocale('de-DE');
$translatableListener->setTranslatableLocale(\Locale::getDefault());
$doctrineEventManager->addEventSubscriber($translatableListener);
If you want to set the DefaultLocale and the TranslatableLocale in Zend Framework 2 for the Translatable Doctrine Extension, than do it in bootstrap and don't add it a second time in the doctrine configuration.
If you want to keep:
'doctrine' => [
'eventmanager' => [
'orm_default' => [
'subscribers' => [
'Gedmo\Timestampable\TimestampableListener',
'Gedmo\Sluggable\SluggableListener',
// the line below because in future you might need it
'Gedmo\Translatable\TranslatableListener',
],
],
],
Try this:
https://stackoverflow.com/a/42859119/3661592
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;
}
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 .
I do not know how to configure Zend \ Log with Doctrine2. Only allows you to write directly to the database via a connection adapter or write to a file.
May be it's too late to answer this question but better late than never.
I've found a good post which explains how to create a basic SQL Logger for ZF2 and Doctrine.
The approach is pretty simple :
1. Creating Logger class : Create the following class in your Module/Application/Log folder :
<?php
namespace Application\Log;
use Zend\Log\Logger;
use Doctrine\DBAL\Logging\DebugStack;
class SqlLogger extends DebugStack
{
protected $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
public function stopQuery()
{
parent::stopQuery();
$q = $this->queries[$this->currentQuery];
$message = "Executed Query: " . print_r($q, true);
$this->logger->info($message);
}
}
The stopQuery() function which is called by Doctrine when it finiches sending the query to the database server, is
overrided so that it could write the current query to the Logger object.
2. Configuring the Logger : Add the following code in your config/autoload/global.php file, to make
the Logger accessible to the Service Manager using the name my_sql_logger :
'service_manager' => array(
'factories' => array(
'my_sql_logger' => function($sm) {
$log = new \Zend\Log\Logger();
$writer = new \Zend\Log\Writer\Stream('./data/logs/sql.log');
$log->addWriter($writer);
$sqllog = new \Application\Log\SqlLogger($log);
return $sqllog;
},
)
),
The Logger will write data to the data/logs/sql.log file. So, make sure that data/logs folder exists in your
application root directory.
3. Configuring Doctrine : Now you need to tell Doctrine to use the created Logger. Just add the following code
to your Doctrine configuration :
return array(
'doctrine' => array(
/*--------Add this code------------*/
'sql_logger_collector' => array(
'orm_default' => array(
'sql_logger' => 'my_sql_logger',
),
),
/*---------------------------------*/
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '3306',
'user' => 'username',
'password' => 'password',
'dbname' => 'dbname',
),
),
),
),
);
With the above configuration of Zend\Log and Doctrine2, you'll get all the query data logged in the
data/log/sql.log file.
Please see this Sql Logger for ZF2 and Doctrine for more details.