ฉันจะอ่านการตั้งค่าการกำหนดค่าจาก Symfony2 config.yml ได้อย่างไร


191

ฉันได้เพิ่มการตั้งค่าไปยังไฟล์ config.yml ของฉันเช่น:

app.config:
    contact_email: somebody@gmail.com
    ...

สำหรับชีวิตของฉันฉันไม่สามารถหาวิธีอ่านมันเป็นตัวแปรได้ ฉันลองอะไรทำนองนี้ในหนึ่งในคอนโทรลเลอร์ของฉัน:

$recipient =
$this->container->getParameter('contact_email');

แต่ฉันได้รับข้อผิดพลาดว่า:

ต้องกำหนดพารามิเตอร์ "contact_email"

ฉันล้างแคชแล้วฉันยังดูทุกที่ในเอกสารประกอบของไซต์ที่โหลดใหม่ของ Symfony2 แต่ฉันไม่สามารถหาวิธีการทำสิ่งนี้ได้

อาจจะเหนื่อยเกินไปที่จะคิดออกตอนนี้ มีใครสามารถช่วยได้บ้าง

คำตอบ:


194

แทนที่จะกำหนดcontact_emailภายในapp.configกำหนดไว้ในparametersรายการ:

parameters:
    contact_email: somebody@gmail.com

คุณควรค้นหาการโทรที่คุณกำลังดำเนินการอยู่ในคอนโทรลเลอร์ของคุณตอนนี้


4
สิ่งนี้จะทำงานกับสภาพแวดล้อม Dev / Prod ได้อย่างไร ดังนั้นสำหรับการทดสอบฉันต้องการอีเมลที่จะส่งไปยังอีเมลทดสอบและฝ่ายผลิตจะได้รับอีเมลอีกฉบับ
Phill Pafford

2
@Phill: หากคุณใช้ swiftmailer มาตรฐานใน symfony2 ของคุณคุณสามารถใช้การตั้งค่าต่อไปนี้ใน config_dev.yml ของคุณ: swiftmailer: delivery_address: dev@example.com คุณสามารถหาข้อมูลเพิ่มเติมได้ในตำราอาหาร Symfony2
Pierre

4
ฉันควรจะฉีดคลาส container ทุกที่ (คอนโทรลเลอร์, เอนทิตี, คลาส) เมื่อฉันใช้คำสั่งนี้$ this-> container-> getParameter ('contact_email'); ? หรือมีวิธีที่ง่ายกว่าในการทำเช่นนั้นโดยไม่ต้องฉีดคลาส container?
webblover

1
ตามวิธีนี้ฉันจะเข้าถึงคุณสมบัติที่ซ้อนกันได้อย่างไร
Ousmane

1
@webblover เพียงใส่พารามิเตอร์ตัวเองโดยใช้%parameter_name%- เครื่องหมาย (ใน YAML)
MauganRa

173

ในขณะที่วิธีการย้ายcontact_emailไปยังparameters.ymlนั้นเป็นเรื่องง่ายตามที่เสนอในคำตอบอื่น ๆ ซึ่งอาจทำให้ไฟล์พารามิเตอร์ของคุณยุ่งเหยิงได้ง่ายหากคุณจัดการกับบันเดิลจำนวนมากหรือหากคุณจัดการกับบล็อกการตั้งค่าที่ซ้อนกัน

  • ก่อนอื่นฉันจะตอบคำถามอย่างเคร่งครัด
  • หลังจากนั้นฉันจะให้วิธีการรับการกำหนดค่าเหล่านั้นจากบริการโดยไม่ต้องผ่านช่องว่างทั่วไปเป็นพารามิเตอร์

วิธีการแรก: บล็อกการตั้งค่าที่แยกออกมารับมันเป็นพารามิเตอร์

ด้วยส่วนขยาย ( เพิ่มเติมเกี่ยวกับส่วนขยายที่นี่ ) คุณสามารถเก็บ "แยก" นี้ไว้ในบล็อกที่แตกต่างกันได้อย่างง่ายดายในconfig.ymlและจากนั้นฉีดเป็นพารามิเตอร์ gettable จากตัวควบคุม

ภายในคลาส Extension ของคุณภายในไดเรคทอรีDependencyInjectionเขียนสิ่งนี้:

class MyNiceProjectExtension extends Extension
{
    public function load( array $configs, ContainerBuilder $container )
    {
        // The next 2 lines are pretty common to all Extension templates.
        $configuration = new Configuration();
        $processedConfig = $this->processConfiguration( $configuration, $configs );

        // This is the KEY TO YOUR ANSWER
        $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ] );

        // Other stuff like loading services.yml
    }

จากนั้นใน config.yml ของคุณ config_dev.yml และเพื่อให้คุณสามารถตั้งค่า

my_nice_project:
    contact_email: someone@example.com

ในการประมวลผลconfig.ymlภายในของMyNiceBundleExtensionคุณคุณจะต้องมีConfigurationคลาสในเนมสเปซเดียวกันด้วย:

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root( 'my_nice_project' );

        $rootNode->children()->scalarNode( 'contact_email' )->end();

        return $treeBuilder;
    }
}

จากนั้นคุณสามารถรับการกำหนดค่าจากคอนโทรลเลอร์ของคุณได้ตามที่คุณต้องการในคำถามเดิม แต่รักษาความparameters.ymlสะอาดและตั้งค่าไว้ในconfig.ymlส่วนที่แยกจากกัน:

$recipient = $this->container->getParameter( 'my_nice_project.contact_email' );

วิธีที่สอง: บล็อกการตั้งค่าที่แยกออกจากกันฉีดการกำหนดค่าลงในบริการ

สำหรับผู้อ่านที่กำลังมองหาสิ่งที่คล้ายกัน แต่สำหรับการปรับแต่งค่าจากการบริการมีวิธีที่ดีกว่าที่ไม่เคยหยุดยั้งพื้นที่ทั่วไป "paramaters" และไม่จำเป็นต้องcontainerส่งผ่านไปยังบริการ หลีกเลี่ยง)

เคล็ดลับข้างต้นยังคง "แทรก" เข้าไปในพื้นที่พารามิเตอร์กำหนดค่าของคุณ

อย่างไรก็ตามหลังจากโหลดคำจำกัดความของบริการแล้วคุณสามารถเพิ่มการเรียกใช้เมธอดเช่นตัวอย่างsetConfig()ที่แทรกบล็อกนั้นลงในบริการเท่านั้น

ตัวอย่างเช่นในคลาส Extension:

class MyNiceProjectExtension extends Extension
{
    public function load( array $configs, ContainerBuilder $container )
    {
        $configuration = new Configuration();
        $processedConfig = $this->processConfiguration( $configuration, $configs );

        // Do not add a paramater now, just continue reading the services.
        $loader = new YamlFileLoader( $container, new FileLocator( __DIR__ . '/../Resources/config' ) );
        $loader->load( 'services.yml' );

        // Once the services definition are read, get your service and add a method call to setConfig()
        $sillyServiceDefintion = $container->getDefinition( 'my.niceproject.sillymanager' );
        $sillyServiceDefintion->addMethodCall( 'setConfig', array( $processedConfig[ 'contact_email' ] ) );
    }
}

จากนั้นในการที่services.ymlคุณกำหนดบริการตามปกติโดยไม่มีการเปลี่ยนแปลงใด ๆ :

services:
    my.niceproject.sillymanager:
        class: My\NiceProjectBundle\Model\SillyManager
        arguments: []

จากนั้นในSillyManagerชั้นเรียนของคุณเพียงเพิ่มวิธี:

class SillyManager
{
    private $contact_email;

    public function setConfig( $newConfigContactEmail )
    {
        $this->contact_email = $newConfigContactEmail;
    }
}

โปรดทราบว่าวิธีนี้ใช้ได้กับอาร์เรย์แทนค่าสเกลาร์! ลองนึกภาพว่าคุณกำหนดค่าแรบบิทคิวและต้องการโฮสต์ผู้ใช้และรหัสผ่าน:

my_nice_project:
    amqp:
        host: 192.168.33.55
        user: guest
        password: guest

แน่นอนคุณต้องเปลี่ยนทรีของคุณ แต่คุณสามารถทำได้:

$sillyServiceDefintion->addMethodCall( 'setConfig', array( $processedConfig[ 'amqp' ] ) );

และจากนั้นในการบริการทำ:

class SillyManager
{
    private $host;
    private $user;
    private $password;

    public function setConfig( $config )
    {
        $this->host = $config[ 'host' ];
        $this->user = $config[ 'user' ];
        $this->password = $config[ 'password' ];
    }
}

หวังว่านี่จะช่วยได้!


หากคุณสงสัยว่ามีอะไรที่แตกต่างกันระหว่างวิธีแรกและเอกสารก็ว่าค่าการตั้งค่าจะถูกแปลงเป็นพารามิเตอร์ในวิธีการที่มีบรรทัดนี้MyNiceProjectExtension->load() $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);ขอบคุณ Xavi!
jxmallett

คำตอบที่สมบูรณ์แบบ symfony ความอับอายไม่อนุญาตให้คุณเข้าถึง config แบบเดียวกับที่ทำกับพารามิเตอร์
Martin Lyne

นี่เป็นคำตอบที่ดี แต่เป็นการเปิดเผยถึงวิธีที่ป้านของ Symfony ในการ "กำหนดค่า" แอปพลิเคชัน อะไรคือจุดของการมีไฟล์กำหนดค่าสภาพแวดล้อมโดยพลการเมื่อคุณต้องเขียนและเรียกใช้บริการเฉพาะเพื่อเข้าถึง มีใครบางคนที่ Symfony ไม่ได้นั่งอยู่ที่นั่นและตระหนักว่า 'บางทีนักพัฒนาอาจต้องการให้ค่าเฉพาะสภาพแวดล้อมในแอปพลิเคชันของพวกเขาที่พวกเขาสามารถเข้าถึงได้' ชนิดของไฟล์กำหนดค่าไม่ใช่หรือ พวกเขากำลังติดตามรูปแบบการออกแบบ "STKTFANREO": ตั้งค่าลูกบิดเป็น F'd และตัด 'em off "
eggmatters

มีหลายแอพพลิเคชั่นโดยเฉพาะอย่างยิ่งในการปรับใช้การทดสอบอัตโนมัติแบบขนานและพิเศษเมื่อทีมพัฒนาบันเดิลซึ่งส่วนใหญ่เป็นแบบจำลองหรือตรรกะที่ใช้โดยทีมอื่น ๆ ในแอพพลิเคชั่นที่แตกต่างกัน อีกอันหนึ่งคือหน้าเว็บของผู้ดูแลระบบและอีกคนหนึ่งคือ REST API แต่ละรายการเป็นแอปพลิเคชันที่แตกต่างกันซึ่งยินดีที่จะกำหนดค่าที่แตกต่างกัน ที่ถูกคูณด้วยสภาพแวดล้อมต่าง ๆ (การผลิตการผลิตก่อนการทดสอบการพัฒนาและอื่น ๆ ) ทำให้สามารถกำหนดค่าได้ 12 หรือ 15 แบบใน บริษัท เดียวได้อย่างง่ายดาย
Xavi Montero

@ XaviMontero ฉันทำตามคำแนะนำของคุณวิธีที่สอง: และเมื่อ var_dump $ this-> contact_email หรือเพิ่ม exit () ในฟังก์ชั่น setConfig () มันไม่ได้ออก ดูเหมือนว่า setConfig จะไม่ถูกเรียก
user742736

35

ฉันต้องเพิ่มคำตอบของดักลาสคุณสามารถเข้าถึงการกำหนดค่าทั่วโลก แต่ symfony แปลพารามิเตอร์บางอย่างเช่น:

# config.yml
... 
framework:
    session:
        domain: 'localhost'
...

เป็น

$this->container->parameters['session.storage.options']['domain'];

คุณสามารถใช้ var_dump เพื่อค้นหาคีย์หรือค่าที่ระบุ


17

เพื่อให้สามารถแสดงพารามิเตอร์การกำหนดค่าบางอย่างสำหรับบันเดิลของคุณคุณควรศึกษาเอกสารประกอบสำหรับการทำเช่นนั้น มันค่อนข้างง่ายที่จะทำ :)

นี่คือลิงค์: วิธีเปิดเผยการกำหนดค่า Semantic สำหรับ Bundle


สุจริตถามคำถามนี้กว่า 2 ปีที่ผ่านมาตอนนั้นบทความข้างต้นไม่ได้อยู่
josef.van.niekerk

10
ฉันเห็นด้วยกับข้อความนั้น ฉันได้ตั้งคำตอบในกรณีที่มีคนเปิดบทความนี้ในปัจจุบัน ขอบคุณสำหรับคะแนนลบ - คุณทำวันของฉัน
Nikola Petkanski

ขอโทษฉันตอนนี้ที่ฉันคิดว่ามัน downvote ของฉันก็ไม่มีเหตุผล ฉันซาบซึ้งในความช่วยเหลือของคุณฉันพยายามอัปโหลด แต่ SO ไม่อนุญาตอีกต่อไป ลิงค์มีประโยชน์มากที่สุดและฉันมั่นใจว่าคนอื่น ๆ จะได้ประโยชน์จากมัน! บางทีผู้ดูแลระบบสามารถช่วยเปลี่ยน downvote ของฉัน ???
josef.van.niekerk

ฉันเชื่อว่าคุณสามารถคลิกอีกครั้งเพื่อยกเลิก
Nikola Petkanski

คุณไม่สามารถยกเลิกการลงคะแนนเกิน X (5?) นาทีหลังจากที่คุณทำหรือจนกว่าข้อความจะถูกแก้ไข
cheesemacfly

7

เช่นเดียวกับที่เคยพูดก่อนหน้านี้ - คุณสามารถเข้าถึงพารามิเตอร์ใด ๆ ได้โดยใช้คอนเทนเนอร์ฉีดและใช้คุณสมบัติพารามิเตอร์

"Symfony - การทำงานกับคำนิยามบริการคอนเทนเนอร์"เป็นบทความที่ดีเกี่ยวกับเรื่องนี้


3

ฉันเรียนรู้วิธีง่ายๆจากตัวอย่างโค้ดของhttp://tutorial.symblog.co.uk/

1) สังเกต ZendeskBlueFormBundle และตำแหน่งไฟล์

# myproject/app/config/config.yml

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: @ZendeskBlueFormBundle/Resources/config/config.yml }

framework:

2) ประกาศ Zendesk_BlueForm.emails.contact_email และตำแหน่งไฟล์

# myproject/src/Zendesk/BlueFormBundle/Resources/config/config.yml

parameters:
    # Zendesk contact email address
    Zendesk_BlueForm.emails.contact_email: dunnleaddress@gmail.com

3) สังเกตว่าฉันได้รับมันใน $ client และตำแหน่งไฟล์ของคอนโทรลเลอร์

# myproject/src/Zendesk/BlueFormBundle/Controller/PageController.php

    public function blueFormAction($name, $arg1, $arg2, $arg3, Request $request)
    {
    $client = new ZendeskAPI($this->container->getParameter("Zendesk_BlueForm.emails.contact_email"));
    ...
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.