2013-02-04 23 views
5

के अंदर से अद्यतन कॉन्फ़िगरेशन एक्सेस करें हम एक कमांड बना रहे हैं जो एक नया डेटाबेस उत्पन्न करने और इसकी स्कीमा बनाने के लिए अन्य आदेशों पर निर्भर करता है। अभी तक हम config.yml फ़ाइल को पढ़ने के लिए सफलतापूर्वक प्राप्त कर चुके हैं, हमारी नई कनेक्शन जानकारी जोड़ें, और फ़ाइल को वापस लिखने के लिए। उसी आदेश में हम डेटाबेस और स्कीमा बनाने के लिए सिम्फनी कमांड चलाने की कोशिश कर रहे हैं: अद्यतन। यह वह जगह है जहां हम समस्याओं में भाग ले रहे हैं। हम आदेश को दूसरी बार कोई त्रुटि क्योंकि अद्यतन विन्यास फाइल आवेदन में ताजा भरी हुई है है चलाते हैंसिम्फनी 2: कमांड

[InvalidArgumentException] Doctrine ORM Manager named "mynewdatabase" does not exist.

: हम निम्नलिखित त्रुटि मिलती है। अगर हम config.yml फ़ाइल में लिखने के बाद मैन्युअल रूप से सिद्धांत कमांड चलाते हैं तो यह त्रुटि के बिना भी काम करता है।

हम सोच रहे हैं कि हमारे आदेश में उस बिंदु पर जहां हम डेटाबेस बना रहे हैं और कमांड अपडेट कर रहे हैं, यह अभी भी config.yml/database.yml के मौजूदा कर्नेल के संस्करण का उपयोग कर रहा है जो स्मृति में संग्रहीत है। हमने भाग्य के बिना एप्लिकेशन/कर्नेल कॉन्फ़िगरेशन (शटडाउन(), बूट() इत्यादि को फिर से शुरू करने के कई अलग-अलग तरीकों का प्रयास किया है। कोड यह रहा:

namespace Test\MyBundle\Command; 

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; 
use Symfony\Component\Console\Input\InputArgument; 
use Symfony\Component\Console\Input\InputInterface; 
use Symfony\Component\Console\Input\InputOption; 
use Symfony\Component\Console\Input\ArrayInput; 
use Symfony\Component\Console\Output\OutputInterface; 
use Symfony\Component\Yaml\Yaml; 

class GeneratorCommand extends ContainerAwareCommand 
{ 
    protected function configure() 
    { 
     $this 
      ->setName('generate') 
      ->setDescription('Create a new database.') 
      ->addArgument('dbname', InputArgument::REQUIRED, 'The db name') 
     ; 
    } 

    /* 
     example: php app/console generate mynewdatabase 
    */ 
    protected function execute(InputInterface $input, OutputInterface $output) 
    { 
     //Without this, the doctrine commands will prematurely end execution 
     $this->getApplication()->setAutoExit(false); 

     //Open up app/config/config.yml 
     $yaml = Yaml::parse(file_get_contents($this->getContainer()->get('kernel')->getRootDir() .'/config/config.yml')); 

     //Take input dbname and use it to name the database 
     $db_name = $input->getArgument('dbname'); 

     //Add that connection to app/config/config.yml 
     $yaml['doctrine']['dbal']['connections'][$site_name] = Array('driver' => '%database_driver%', 'host' => '%database_host%', 'port' => '%database_port%', 'dbname' => $site_name, 'user' => '%database_user%', 'password' => '%database_password%', 'charset' => 'UTF8'); 
     $yaml['doctrine']['orm']['entity_managers'][$site_name] = Array('connection' => $site_name, 'mappings' => Array('MyCustomerBundle' => null)); 

     //Now put it back 
     $new_yaml = Yaml::dump($yaml, 5); 
     file_put_contents($this->getContainer()->get('kernel')->getRootDir() .'/config/config.yml', $new_yaml); 

     /* http://symfony.com/doc/current/components/console/introduction.html#calling-an-existing-command */ 

     //Set up our db create script arguments 
     $args = array(
     'command'  => 'doctrine:database:create', 
     '--connection' => $site_name, 
    ); 
     $db_create_input = new ArrayInput($args); 

     //Run the symfony database create arguments 
     $this->getApplication()->run($db_create_input, $output); 

     //Set up our schema update script arguments 
     $args = array(
     'command' => 'doctrine:schema:update', 
     '--em'  => $site_name, 
     '--force' => true 
    ); 
     $update_schema_input = new ArrayInput($args); 

     //Run the symfony database create command 
     $this->getApplication()->run($update_schema_input, $output); 
    } 
} 

उत्तर

3

क्योंकि डीआईसी एक संकलन प्रक्रिया से गुजरता है और फिर एक PHP फ़ाइल में तो वर्तमान चल रहा है की प्रक्रिया में शामिल किया गया है करने के लिए लिखा है कारण यह काम नहीं करता है। जिसे आप यहां देख सकते हैं:

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Kernel.php#L562

आप सेवा निर्धारण न तो बदल और फिर इन परिवर्तनों को संकलित करने के लिए "रिबूट" करने के लिए कर्नेल कोशिश यह संकलित फ़ाइल को दूसरी बार (require_once) शामिल नहीं चलते हैं और यह पुरानी संकलित सेवा परिभाषाओं के साथ पहले से ही शामिल डीआईसी कक्षा का एक और उदाहरण बनायेगा।

मैं इस बारे में सोचने का सबसे आसान तरीका एक खाली कर्नेल क्लास बनाना चाहता हूं जो आपके ऐप कर्नेल को विस्तारित करता है। इसलिए जैसा:

<?php 

namespace Test\MyBundle\Command; 

class FakeKernel extends \AppKernel 
{ 
} 
फिर अपने आदेश में

, आप के बाद आप नई सेवा परिभाषाएँ सहेज कर रखा है इस कर्नेल बूट कर सकते हैं और यह के भाग के रूप "FakeKernel" नाम का उपयोग कर एक नया डीआईसी वर्ग फिर से संकलित कर देगा फ़ाइल का नाम जिसका अर्थ है कि यह शामिल होगा। इसलिए जैसे:

$kernel = new \Test\MyBundle\Command\FakeKernel($input->getOption('env'), true); 
$application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel); 

तो फिर तुम इस नए आवेदन के खिलाफ अपने उप आदेशों जो नए डीआईसी के साथ चल रहे हो जाएगा चलाएँ:

$application->run($db_create_input, $output); 

अस्वीकरण: यह बहुत ही hacky महसूस करता है। मैं अन्य समाधान/कामकाज सुनने के लिए खुला हूं।

+0

मैट आपका सुझाव स्पॉट-ऑन है। मैंने AdminBundle के तहत एक नया 'सेवा' फ़ोल्डर बनाया और वहां एक नया 'कमांडर्नल' वर्ग डाला। इसने एक जादू की तरह काम किया। धन्यवाद एक मीट्रिक टन! – lewsid

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^