skip to Main Content

We have memcache on our Symfony 3.4 app:

cache:
    app: cache.adapter.memcached
    default_memcached_provider: "%app.memcached.dsn%"

However, we’ve been asked to use several cache servers, so just passing one DSN is no good.

Looking here (https://symfony.com/blog/new-in-symfony-3-3-memcached-cache-adapter), I see you can create it in code like this:

$client = MemcachedAdapter::createConnection(array(
    // format => memcached://[user:pass@][ip|host|socket[:port]][?weight=int]
    // 'weight' ranges from 0 to 100 and it's used to prioritize servers
    'memcached://my.server.com:11211'
    'memcached://rmf:abcdef@localhost'
    'memcached://127.0.0.1?weight=50'
    'memcached://username:the-password@/var/run/memcached.sock'
    'memcached:///var/run/memcached.sock?weight=20'
)); 

However, that isn’t autowired.

I believe we need to either make a provider class, or somehow get it to make calls to addServer($dsn), once instantiated. I also saw the following on random posts:

memcache:
    class: Memcached
    calls:
        - [ addServer, [ %app.memcached.dsn.1% ]]
        - [ addServer, [ %app.memcached.dsn.2% ]]

However it isn’t really helping or I have missed something out.

Can anyone help? How do I create this provider class?

2

Answers


  1. You can copy above code snippet as a service configuration to your services.yaml, which probably roughly looks like this:

    # app/config/services.yaml
    
    services:
        app.memcached_client:
            class: Memcached
            factory: 'SymfonyComponentCacheAdapterMemcachedAdapter::createConnection'
            arguments: [['memcached://my.server.com:11211', 'memcached://rmf:abcdef@localhost']]
    
        app.memcached_adapter:
            class: SymfonyComponentCacheAdapterMemcachedAdapter
            arguments:
                - '@app.memcached_client'
    

    Then in your configuration you should be able to reference the adapter using the client created by the factory, e.g. something like:

    # app/config/config.yaml
    
    framework:
        cache:
            app: app.memcached_adapter
    

    You might also be able to overwrite the default alias cache.adapter.memcached instead of having your own adapter.

    Your approach using Memcached::addServer might work as well, but just like with MemcachedAdapter::createConnection this will return the Client, which needs to be passed to the cache adapter. That’s why there is a second service app.memcached_adapter, which is used in the cache configuration.

    Please be aware that I have not tested this, so this is rather a rough outline than a fully working solution,

    Login or Signup to reply.
  2. For one of my projects running Symfony 3.4 the configuration was simpler:

    Create a service that will be used as a client:

    app.memcached_client:
        class: Memcached
        factory: ['AppBundleServicesMemcached', 'createConnection']
        arguments: ['memcached://%memcache_ip%:%memcache_port%']
    

    The AppBundleServicesMemcached can have all the custom logic I need like so:

    class Memcached
    {
        public static function createConnection($dns)
        {
            $options = [
                'persistent_id' => 'some id'
            ];
    
            // Some more custom logic. Maybe adding some custom options
            // For example for AWS Elasticache
    
            if (defined('Memcached::OPT_CLIENT_MODE') && defined('Memcached::DYNAMIC_CLIENT_MODE')) {
                $options['CLIENT_MODE'] = Memcached::DYNAMIC_CLIENT_MODE;
            }
    
            return SymfonyComponentCacheAdapterMemcachedAdapter::createConnection($dns, $options);
        }
    }
    

    And then I used that service in my config.yml:

    framework:
        cache:
            default_memcached_provider: app.memcached_client
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search