Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Drupal Bundle Laravel Package

ekino/drupal-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require ekino/drupal-bundle
    

    Ensure your project structure matches:

    SymfonyRoot/
    ├── app/
    ├── vendor/
    ├── src/
    └── web/  # Drupal 7 source (document root)
    
  2. Configure index.php: Replace Drupal’s index.php with the provided snippet to share the Symfony container:

    require __DIR__.'/../app/bootstrap.php.cache';
    $kernel = new AppKernel('prod', false);
    $kernel->boot();
    $container = $kernel->getContainer();
    \Drupal::setContainer($container); // Critical for service sharing
    
  3. First Use Case: Use Symfony’s services in a Drupal command (e.g., drush):

    // In a custom Drush command (e.g., `app/console drush my:command`)
    use Symfony\Component\DependencyInjection\ContainerInterface;
    $container = \Drupal::getContainer();
    $logger = $container->get('logger'); // Access Symfony service
    $logger->info('Drupal + Symfony integration works!');
    

Implementation Patterns

1. Service Sharing

  • Drupal → Symfony: Inject Symfony services into Drupal modules/services via hook_service_alter():

    function MYMODULE_service_alter(&$services) {
      $services['my.drupal_service'] = array(
        'class' => 'My\Service',
        'arguments' => ['@logger'], // Inject Symfony service
      );
    }
    
  • Symfony → Drupal: Access Drupal services from Symfony controllers/commands:

    // In a Symfony controller
    $drupalDatabase = \Drupal::database();
    $users = $drupalDatabase->query("SELECT * FROM {users}")->fetchAll();
    

2. Command-Line Integration

  • Extend Drush: Create Symfony commands that interact with Drupal:
    // src/AppBundle/Command/DrupalBackupCommand.php
    namespace AppBundle\Command;
    use Symfony\Component\Console\Command\Command;
    use Symfony\Component\Console\Input\InputInterface;
    use Symfony\Component\Console\Output\OutputInterface;
    
    class DrupalBackupCommand extends Command {
      protected function execute(InputInterface $input, OutputInterface $output) {
        $backup = \Drupal::service('backup');
        $backup->create();
        $output->writeln('Backup done!');
      }
    }
    
    Register in app/config/commands.yml:
    commands:
      app:drupal_backup: DrupalBackupCommand
    

3. Event Dispatching

  • Symfony Events in Drupal: Listen to Drupal events from Symfony:

    // In a Symfony service
    $eventDispatcher = $container->get('event_dispatcher');
    $eventDispatcher->addListener('hook_cron_run', function() {
      // Handle Drupal cron events
    });
    
  • Drupal Events in Symfony: Use \Drupal::moduleHandler()->invokeAll() to trigger Drupal hooks:

    \Drupal::moduleHandler()->invokeAll('my_custom_hook');
    

4. Routing Integration

  • Shared Routes: Define routes in Symfony’s routing.yml and reuse them in Drupal templates:
    {{
      path({
        '_route': 'app.my_route',
        '_parameters': { 'id': node.id }
      })
    }}
    

Gotchas and Tips

Pitfalls

  1. Container Initialization Order:

    • Error: Drupal::service() fails with ServiceNotFoundException.
    • Fix: Ensure index.php calls $kernel->boot() before \Drupal::setContainer().
    • Debug: Check if AppKernel is properly loaded by inspecting var/cache/dev/appDevProjectContainer.xml.
  2. Circular Dependencies:

    • Error: Symfony/Drupal services fail to autowire due to circular references.
    • Fix: Use setters or constructor injection carefully. Prefer lazy-loading services:
      $service = $container->get('service_id')->setDrupalDependency(\Drupal::service('drupal_service'));
      
  3. Drush Compatibility:

    • Error: drush commands fail with Class not found.
    • Fix: Ensure vendor/bin/drush is used (not global Drush). Add to composer.json:
      "bin-dir": "vendor/bin"
      
  4. Caching Conflicts:

    • Error: Changes to Symfony services aren’t reflected in Drupal.
    • Fix: Clear both caches:
      php app/console cache:clear
      drush cc all
      

Debugging Tips

  • Symfony Debug Toolbar: Enable in config_dev.yml to inspect services:

    framework:
      profiler: { only_exceptions: false }
    

    Access at /_profiler.

  • Drupal Logs: Redirect Symfony logs to Drupal’s watchdog:

    $logger = $container->get('logger');
    $logger->addHandler(new \Drupal\Core\Logger\DrupalLoggerHandler('drupal_logger'));
    
  • Dependency Injection: Dump services for debugging:

    $container->get('debug.container')->dump();
    

Extension Points

  1. Custom Service Providers: Extend Drupal’s service container by creating a Symfony service provider:

    // src/AppBundle/Drupal/DrupalServiceProvider.php
    namespace AppBundle\Drupal;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Definition;
    
    class DrupalServiceProvider {
      public function load(ContainerBuilder $container) {
        $definition = new Definition('My\DrupalService');
        $definition->addArgument('@drupal.database');
        $container->setDefinition('my.drupal_service', $definition);
      }
    }
    

    Register in app/config/config.yml:

    imports:
      - { resource: drupal-services.yml }
    
  2. Override Drupal Services: Use Symfony’s compiler passes to modify Drupal services:

    // src/AppBundle/DependencyInjection/Compiler/DrupalPass.php
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    
    class DrupalPass implements CompilerPassInterface {
      public function process(ContainerBuilder $container) {
        $definition = $container->findDefinition('drupal.service');
        $definition->addMethodCall('setCustomOption', ['value']);
      }
    }
    

    Tag in services.yml:

    services:
      app.drupal_pass:
        class: AppBundle\DependencyInjection\Compiler\DrupalPass
        tags: [compiler_pass]
    
  3. Environment-Specific Config: Use Symfony’s %kernel.environment% to switch Drupal behaviors:

    # app/config/config_dev.yml
    drupal:
      debug_mode: true
      cache: false
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware