Làm cách nào để đọc cài đặt cấu hình từ Symfony2 config.yml?


191

Tôi đã thêm một cài đặt vào tệp config.yml của mình như sau:

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

Đối với cuộc sống của tôi, tôi không thể tìm ra cách đọc nó thành một biến. Tôi đã thử một cái gì đó như thế này trong một trong những bộ điều khiển của tôi:

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

Nhưng tôi nhận được một lỗi nói:

Tham số "contact_email" phải được xác định.

Tôi đã xóa bộ nhớ cache của mình, tôi cũng đã tìm mọi nơi trên tài liệu trang web được tải lại của Symfony2, nhưng tôi không thể tìm ra cách để làm điều này.

Có lẽ chỉ là quá mệt mỏi để tìm ra điều này bây giờ. Bất cứ ai có thể giúp đỡ với điều này?

Câu trả lời:


194

Thay vì xác định contact_emailbên trong app.config, hãy xác định nó trong một parametersmục:

parameters:
    contact_email: somebody@gmail.com

Bạn sẽ tìm thấy cuộc gọi bạn đang thực hiện trong bộ điều khiển của bạn bây giờ hoạt động.


4
Làm thế nào điều này sẽ làm việc với môi trường Dev / Prod? Vì vậy, để thử nghiệm, tôi muốn gửi email đến email thử nghiệm và sản xuất sẽ nhận được một email khác
Phill Pafford

2
@Phill: Nếu bạn đang sử dụng swiftmailer tiêu chuẩn trong symfony2, bạn có thể sử dụng cài đặt sau trong config_dev.yml: swiftmailer: delivery_address: dev@example.com Bạn có thể tìm thêm thông tin trong sách nấu ăn Symfony2
Pierre

4
Tôi có nên tiêm lớp container ở mọi nơi (bộ điều khiển, thực thể, lớp) khi tôi sử dụng câu lệnh này $ this-> container-> getParameter ('contact_email'); ? hoặc có một cách đơn giản hơn để làm như vậy mà không cần tiêm lớp container?
webblover

1
Theo giải pháp này làm thế nào tôi có thể truy cập vào các thuộc tính lồng nhau?
Ousmane

1
@webblover Chỉ cần chèn chính tham số bằng cách sử dụng %parameter_name%ký hiệu - (trong YAML)
MauganRa

173

Mặc dù giải pháp di chuyển contact_emailđến parameters.ymldễ dàng, như được đề xuất trong các câu trả lời khác, điều đó có thể dễ dàng làm lộn xộn tệp tham số của bạn nếu bạn xử lý nhiều gói hoặc nếu bạn xử lý các khối cấu hình lồng nhau.

  • Đầu tiên, tôi sẽ trả lời đúng câu hỏi.
  • Sau đó, tôi sẽ đưa ra một cách tiếp cận để nhận các cấu hình đó từ các dịch vụ mà không bao giờ đi qua một không gian chung dưới dạng tham số.

TIẾP CẬN ĐẦU TIÊN: Khối cấu hình tách biệt, lấy nó làm tham số

Với một tiện ích mở rộng ( nhiều hơn về các tiện ích mở rộng tại đây ), bạn có thể giữ phần này dễ dàng "tách" thành các khối khác nhau trong config.ymlvà sau đó thêm vào đó như một tham số có thể truy cập được từ bộ điều khiển.

Trong lớp mở rộng của bạn bên trong DependencyInjectionthư mục viết này:

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
    }

Sau đó, trong config.yml, config_dev.yml và do đó bạn có thể đặt

my_nice_project:
    contact_email: someone@example.com

Để có thể xử lý rằng config.ymlbên trong MyNiceBundleExtensionbạn cũng sẽ cần một Configurationlớp trong cùng một không gian tên:

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

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

        return $treeBuilder;
    }
}

Sau đó, bạn có thể nhận cấu hình từ bộ điều khiển của mình, như bạn muốn trong câu hỏi ban đầu của mình, nhưng giữ parameters.ymlsạch sẽ và đặt nó trong các config.ymlphần riêng biệt:

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

TIẾP CẬN THỨ HAI: Khối cấu hình tách biệt, đưa cấu hình vào dịch vụ

Đối với những độc giả đang tìm kiếm một cái gì đó tương tự nhưng để có được cấu hình từ một dịch vụ, thậm chí còn có một cách tốt hơn mà không bao giờ làm xáo trộn không gian chung của "paramaters" và thậm chí không cần phải containerchuyển đến dịch vụ (thông qua toàn bộ container tránh).

Thủ thuật trên vẫn "tiêm" vào không gian tham số cấu hình của bạn.

Tuy nhiên, sau khi tải định nghĩa của bạn về dịch vụ, bạn có thể thêm một cuộc gọi phương thức, ví dụ như setConfig()chỉ tiêm khối đó vào dịch vụ.

Ví dụ: trong lớp Mở rộng:

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' ] ) );
    }
}

Sau đó, services.ymlbạn xác định dịch vụ của mình như bình thường, không có bất kỳ thay đổi tuyệt đối nào:

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

Và sau đó trong SillyManagerlớp của bạn , chỉ cần thêm phương thức:

class SillyManager
{
    private $contact_email;

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

Lưu ý rằng điều này cũng hoạt động cho mảng thay vì giá trị vô hướng! Hãy tưởng tượng rằng bạn định cấu hình hàng đợi thỏ và cần máy chủ, người dùng và mật khẩu:

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

Tất nhiên bạn cần thay đổi Cây của mình, nhưng sau đó bạn có thể làm:

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

và sau đó trong dịch vụ làm:

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

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

Hi vọng điêu nay co ich!


Nếu bạn đang tự hỏi có gì khác nhau giữa cách tiếp cận đầu tiên và tài liệu, thì đó là các giá trị cấu hình được chuyển đổi thành các tham số trong MyNiceProjectExtension->load()phương thức với dòng này : $container->setParameter( 'my_nice_project.contact_email', $processedConfig[ 'contact_email' ]);. Cảm ơn Xavi!
jxmallett

Câu trả lời hoàn hảo, symfony xấu hổ không cho phép bạn truy cập cấu hình giống như cách nó làm tham số.
Martin Lyne

Đây là một câu trả lời hay, nhưng nó phơi bày cách thức "cấu hình" ứng dụng khó hiểu của Symfony. Điểm quan trọng của việc có các tệp cấu hình môi trường tùy ý khi bạn phải viết và gọi các dịch vụ cụ thể để truy cập chúng là gì. Không phải ai đó ở Symfony ngồi đó và nhận ra, 'Có lẽ các nhà phát triển thực sự muốn cung cấp các giá trị cụ thể cho môi trường trong các ứng dụng của họ mà họ có thể truy cập' Loại điểm của các tệp cấu hình phải không? Họ đang theo mô hình thiết kế "STKTFANREO": "Đặt các nút thành F'd và tách chúng ra"
eggmatters

Nó có một số ứng dụng, đặc biệt là triển khai thử nghiệm tự động song song và đặc biệt khi một nhóm phát triển một gói chủ yếu là mô hình hoặc logic được một số nhóm khác sử dụng trong các ứng dụng khác nhau, ví dụ như một ứng dụng là giao diện người dùng, một cái khác là mặt trước web của bảng quản trị và một cái khác là API REST. Mỗi trong số đó là một ứng dụng khác nhau sẵn sàng cấu hình khác nhau. Điều đó được nhân lên bởi một số môi trường (sản xuất, tiền sản xuất, thử nghiệm, phát triển, v.v.). Điều này dễ dàng mang lại 12 hoặc 15 cấu hình trong một công ty.
Xavi Montero

@XaviMontero Tôi đã làm theo hướng dẫn của bạn THỨ HAI TIẾP CẬN: và khi var_dump $ this-> contact_email hoặc thêm exit () trong hàm setConfig () thì nó không thoát. Có vẻ như setConfig không được gọi
user742736

35

Tôi phải thêm vào câu trả lời của douecraft, bạn có thể truy cập cấu hình toàn cầu, nhưng symfony dịch một số tham số, ví dụ:

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

Chúng tôi

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

Bạn có thể sử dụng var_dump để tìm kiếm một khóa hoặc giá trị được chỉ định.


17

Để có thể hiển thị một số tham số cấu hình cho gói của bạn, bạn nên tham khảo tài liệu để làm như vậy. Nó khá dễ làm :)

Đây là liên kết: Cách hiển thị Cấu hình ngữ nghĩa cho gói


Thành thật mà nói, câu hỏi này đã được hỏi hơn 2 năm trước, hồi đó, bài viết trên không tồn tại.
josef.van.niekerk

10
Tôi đồng ý với tuyên bố đó. Tôi đã đặt câu trả lời trong trường hợp ai đó mở bài viết này ngày nay. Cảm ơn cho đánh giá tiêu cực - bạn đã thực hiện ngày của tôi.
Nikola Petkanski

Lời xin lỗi của tôi, bây giờ tôi nghĩ về nó, downvote của tôi đã không được chấp nhận. Tôi đánh giá cao sự đóng góp của bạn, tôi đã cố gắng nâng cao nhưng SO không cho phép nó nữa. Liên kết này hữu ích nhất và tôi chắc chắn những người khác sẽ được hưởng lợi từ nó! Có lẽ admin có thể giúp thay đổi downvote của tôi ???
josef.van.niekerk

Tôi tin rằng bạn có thể nhấp một lần nữa để hoàn tác.
Nikola Petkanski

Bạn không thể hoàn tác phiếu bầu của mình nhiều hơn X (5?) Sau khi bạn đã hoàn thành hoặc cho đến khi tin nhắn được chỉnh sửa
cheesemacfly


3

Tôi đã học được một cách dễ dàng từ ví dụ mã của http://tutorial.symblog.co.uk/

1) chú ý vị trí tệp và tệp ZendeskBlueFormBundle

# myproject/app/config/config.yml

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

framework:

2) thông báo Zendesk_BlueForm.emails.contact_email và vị trí tệp

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

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

3) chú ý cách tôi lấy nó trong $ client và vị trí tệp của bộ điều khiển

# 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"));
    ...
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.