क्या वास्तव में सिम्फनी 2.x में सब कुछ एक बंडल होना चाहिए?


205

मैं इस तरह के सवालों से अवगत हूं , जहां लोग सामान्य सिम्फनी 2 के बंडल की अवधारणा पर चर्चा करते हैं।

बात यह है कि एक विशिष्ट अनुप्रयोग में, जैसे, उदाहरण के लिए, एक ट्विटर-जैसी एप्लिकेशन, क्या सब कुछ वास्तव में एक सामान्य बंडल के अंदर होना चाहिए, जैसे कि आधिकारिक डॉक्स कहते हैं?

इसका कारण मैं यह पूछ रहा हूं क्योंकि जब हम अनुप्रयोगों का विकास करते हैं, तो सामान्य तौर पर, हम अपने कोड को कुछ पूर्ण-स्टैक गोंद फ्रेमवर्क के लिए अत्यधिक युगल नहीं करना चाहते हैं।

अगर मैं एक सिम्फनी 2 आधारित एप्लिकेशन विकसित करता हूं और कुछ बिंदु पर, मैं तय करता हूं कि सिम्फनी 2 वास्तव में विकास को बनाए रखने के लिए सबसे अच्छा विकल्प नहीं है , तो क्या यह मेरे लिए एक समस्या होगी?

तो सामान्य सवाल यह है कि सब कुछ एक अच्छी बात क्यों है?

संपादित करें # 1

लगभग एक साल बाद जब मैंने यह सवाल पूछा तो मैंने इस विषय पर अपना ज्ञान साझा करने के लिए एक लेख लिखा ।


1
यह केवल एक टिप्पणी है, उत्तर नहीं। मैं व्यक्तिगत रूप से सोचता हूं, हमें परियोजना शुरू करने से पहले सावधानी से रूपरेखा का चयन करना चाहिए। हर ढांचे का सामान करने का अपना तरीका होता है, इसलिए यह उस तरह से सबसे अच्छा समर्थन करने के लिए उपकरण प्रदान करेगा। यदि हमें वह तरीका पसंद है, तो हम अनुसरण करते हैं। वहाँ अन्य विकल्प हैं। हम आरी के बजाय लकड़ी काटने के लिए चाकू का उपयोग नहीं करना चाहते हैं। लेकिन यह एक बहुत ही दिलचस्प सवाल है जिसे आपने :) :)
Anh Nguyen

जवाबों:


219

मैंने इस विषय पर अधिक गहन और अद्यतन ब्लॉग पोस्ट लिखी है: http://elnur.pro/symfony-without-fundun/


नहीं, सब कुछ एक बंडल में नहीं होना चाहिए। आपके पास इस तरह की संरचना हो सकती है:

  • src/Vendor/Model - मॉडल के लिए,
  • src/Vendor/Controller - नियंत्रकों के लिए,
  • src/Vendor/Service - सेवाओं के लिए,
  • src/Vendor/Bundle- बंडलों के लिए, जैसे src/Vendor/Bundle/AppBundle,
  • आदि।

इस तरह, आप AppBundleकेवल उस सामान को डालेंगे जो वास्तव में Symfony2 विशिष्ट है। यदि आप बाद में किसी अन्य फ्रेमवर्क पर जाने का निर्णय लेते हैं, तो आपको Bundleनामस्थान से छुटकारा मिल जाएगा और इसे चुने गए फ्रेमवर्क सामान के साथ बदल दिया जाएगा।

कृपया ध्यान दें कि मैं यहाँ जो सुझाव दे रहा हूं वह ऐप विशिष्ट कोड के लिए है। पुन: प्रयोज्य बंडलों के लिए, मैं अभी भी सर्वोत्तम प्रथाओं का उपयोग करने का सुझाव देता हूं ।

बंडलों से संस्थाओं को बाहर रखना

src/Vendor/Modelकिसी भी बंडल के बाहर संस्थाओं को रखने के लिए , मैंने doctrineअनुभाग को इसमें config.ymlसे बदल दिया है

doctrine:
    # ...
    orm:
        # ...
        auto_mapping: true

सेवा

doctrine:
    # ...
    orm:
        # ...
        mappings:
            model:
                type: annotation
                dir: %kernel.root_dir%/../src/Vendor/Model
                prefix: Vendor\Model
                alias: Model
                is_bundle: false

संस्थाओं के नाम - डॉक्ट्रिन रिपॉजिटरी से एक्सेस करने के लिए - Modelइस मामले में शुरू करते हैं , उदाहरण के लिए Model:User,।

आप समूह से संबंधित संस्थाओं को एक साथ उप-नाम का उपयोग कर सकते हैं, उदाहरण के लिए src/Vendor/User/Group.php,। इस स्थिति में, इकाई का नाम है Model:User\Group

नियंत्रकों को बंडलों से बाहर रखना

सबसे पहले, आपको JMSDiExtraBundle को srcयह कहते हुए सेवाओं के लिए फ़ोल्डर को स्कैन करना होगा config.yml:

jms_di_extra:
    locations:
        directories: %kernel.root_dir%/../src

फिर आप नियंत्रकों को सेवाओं के रूप में परिभाषित करते हैं और उन्हें Controllerनाम स्थान के नीचे रखते हैं :

<?php
namespace Vendor\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use JMS\DiExtraBundle\Annotation\Service;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\SecurityExtraBundle\Annotation\Secure;
use Elnur\AbstractControllerBundle\AbstractController;
use Vendor\Service\UserService;
use Vendor\Model\User;

/**
 * @Service("user_controller", parent="elnur.controller.abstract")
 * @Route(service="user_controller")
 */
class UserController extends AbstractController
{
    /**
     * @var UserService
     */
    private $userService;

    /**
     * @InjectParams
     *
     * @param UserService $userService
     */
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    /**
     * @Route("/user/add", name="user.add")
     * @Template
     * @Secure("ROLE_ADMIN")
     *
     * @param Request $request
     * @return array
     */
    public function addAction(Request $request)
    {
        $user = new User;
        $form = $this->formFactory->create('user', $user);

        if ($request->getMethod() == 'POST') {
            $form->bind($request);

            if ($form->isValid()) {
                $this->userService->save($user);
                $request->getSession()->getFlashBag()->add('success', 'user.add.success');

                return new RedirectResponse($this->router->generate('user.list'));
            }
        }

        return ['form' => $form->createView()];
    }

    /**
     * @Route("/user/profile", name="user.profile")
     * @Template
     * @Secure("ROLE_USER")
     *
     * @param Request $request
     * @return array
     */
    public function profileAction(Request $request)
    {
        $user = $this->getCurrentUser();
        $form = $this->formFactory->create('user_profile', $user);

        if ($request->getMethod() == 'POST') {
            $form->bind($request);

            if ($form->isValid()) {
                $this->userService->save($user);
                $request->getSession()->getFlashBag()->add('success', 'user.profile.edit.success');

                return new RedirectResponse($this->router->generate('user.view', [
                    'username' => $user->getUsername()
                ]));
            }
        }

        return [
            'form' => $form->createView(),
            'user' => $user
        ];
    }
}

ध्यान दें कि मैं सेवाओं के रूप में परिभाषित नियंत्रकों को सरल बनाने के लिए अपने ElnurAbstractControllerBundle का उपयोग कर रहा हूं ।

आखिरी बात यह है कि सिम्फनी को बंडलों के बिना टेम्पलेट्स की तलाश करने के लिए कहना है। मैं टेम्पलेट अनुमानक सेवा को ओवरराइड करके ऐसा करता हूं, लेकिन चूंकि सिम्फनी 2.0 और 2.1 के बीच दृष्टिकोण अलग है, मैं उन दोनों के लिए संस्करण प्रदान कर रहा हूं।

सिम्फनी 2.1+ टेम्प्लेट अनुमानक को ओवरराइड करना

मैंने एक बंडल बनाया है जो आपके लिए करता है।

सिम्फनी 2.0 टेम्पलेट श्रोता को ओवरराइड करना

सबसे पहले, कक्षा को परिभाषित करें:

<?php
namespace Vendor\Listener;

use InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener as FrameworkExtraTemplateListener;
use JMS\DiExtraBundle\Annotation\Service;

class TemplateListener extends FrameworkExtraTemplateListener
{
    /**
     * @param array   $controller
     * @param Request $request
     * @param string  $engine
     * @throws InvalidArgumentException
     * @return TemplateReference
     */
    public function guessTemplateName($controller, Request $request, $engine = 'twig')
    {
        if (!preg_match('/Controller\\\(.+)Controller$/', get_class($controller[0]), $matchController)) {
            throw new InvalidArgumentException(sprintf('The "%s" class does not look like a controller class (it must be in a "Controller" sub-namespace and the class name must end with "Controller")', get_class($controller[0])));

        }

        if (!preg_match('/^(.+)Action$/', $controller[1], $matchAction)) {
            throw new InvalidArgumentException(sprintf('The "%s" method does not look like an action method (it does not end with Action)', $controller[1]));
        }

        $bundle = $this->getBundleForClass(get_class($controller[0]));

        return new TemplateReference(
            $bundle ? $bundle->getName() : null,
            $matchController[1],
            $matchAction[1],
            $request->getRequestFormat(),
            $engine
        );
    }

    /**
     * @param string $class
     * @return Bundle
     */
    protected function getBundleForClass($class)
    {
        try {
            return parent::getBundleForClass($class);
        } catch (InvalidArgumentException $e) {
            return null;
        }
    }
}

और फिर सिम्फनी को इसे जोड़कर इसका उपयोग करने के लिए कहें config.yml:

parameters:
    jms_di_extra.template_listener.class: Vendor\Listener\TemplateListener

बंडलों के बिना टेम्पलेट्स का उपयोग करना

अब, आप बंडलों में से टेम्पलेट्स का उपयोग कर सकते हैं। उन्हें app/Resources/viewsफोल्डर के नीचे रखें । उदाहरण के लिए, ऊपर दिए गए उदाहरण नियंत्रक से उन दो कार्यों के लिए टेम्प्लेट स्थित हैं:

  • app/Resources/views/User/add.html.twig
  • app/Resources/views/User/profile.html.twig

एक टेम्पलेट का जिक्र करते समय, बंडल भाग को छोड़ दें:

{% include ':Controller:view.html.twig' %}

2
यह वास्तव में एक बहुत ही दिलचस्प दृष्टिकोण है। इसके साथ, मैं वास्तविक बंडलों को भी विकसित कर सकता हूं जिसमें विशिष्ट सेट शामिल हैं जो समुदाय उपयोग कर सकता है, बिना अपने आवेदन को शायद ही फ्रेमवर्क में जोड़े।
डैनियल रिबेरो

57
कोड को आप समुदाय के साथ साझा करने के लिए सिम्फनी 2 के साथ युग्मित नहीं करते हैं, तो आप सामान्य सामान को एक पुस्तकालय में रख सकते हैं और फिर एक बंडल बना सकते हैं जो उस लाइब्रेरी को सिम्फनी 2 के साथ एकीकृत करता है।
एलेन अब्दुर्रखिमोव

9
यह एक दिलचस्प विचार है जब तक आप किसी भी कोड पीढ़ी कमांड पर भरोसा नहीं करते। generate:doctrine:crudउदाहरण के लिए इकाई के लिए (= elnur के मामले में मॉडल) काम करने के लिए एक बंडल के अंदर होने की उम्मीद है।
geca

2
इस दृष्टिकोण के साथ सीएलआई ऐप / कंसोल इंटरफ़ेस की कार्यक्षमता को पुनः प्राप्त करने का कोई तरीका है? मुझे अपने मॉडल को किसी भी बंडल के बाहर स्पॉट में रखने का विचार पसंद है, लेकिन मैं सीएलआई कार्यक्षमता तक पहुंच बनाए रखना चाहता हूं।
एंडी बेयर्ड

3
यह एक बंडल में डाला जाना चाहिए :)
d0001

20

बेशक आप अपने आवेदन को कम कर सकते हैं। बस इसे एक पुस्तकालय के रूप में विकसित करें और इसे सिम्फनी- vendor/फोल्डर में एकीकृत करें (या तो उपयोग करके depsया composer.json, आप जिस पर निर्भर करते हैं, आप सिम्फनी 2.0 या सिम्फनी 2.1 का उपयोग करते हैं)। हालांकि, आपको कम से कम एक बंडल की आवश्यकता है, जो आपके पुस्तकालय के "फ्रंटेंड" के रूप में कार्य करता है, जहां Symfony2 नियंत्रक (और इस तरह) पाता है।


2
टैग के कारण symfony-2.0मुझे लगता है कि आप वर्तमान 2.0 संस्करण का उपयोग करेंगे। इस मामले में एक गिट रिपॉजिटरी बनाएं जहां भी आप चाहें और इसमें सब कुछ डाल दें, जिसे आप सिम्फनी से स्वतंत्र विकसित करना चाहते हैं। अपने सिम्फनी-प्रोजेक्ट अपडेट में अपने- depsजैसे को यहां बताए गए जैसे symfony.com/doc/current/cookbook/workflow/… फिर सिम्फनीphp app/console generate:bundle -विशिष्ट सामान के लिए केवल एक (या अधिक) एप्लिकेशन-बंडल (ओं) बनाएं ।
KingCrunch

11

एक सामान्य सिम्फनी वितरण बिना किसी अतिरिक्त (एप्लिकेशन) बंडल के काम कर सकता है, यह इस बात पर निर्भर करता है कि आप फुल स्टैक फ्रेमवर्क से कितनी कार्यक्षमता का उपयोग करना चाहते हैं।

उदाहरण के लिए, आपके नियंत्रक कोई भी कॉल करने योग्य हो सकते हैं जिन्हें आपके प्रोजेक्ट संरचना में कहीं भी रखा जा सकता है, जैसे ही वे ऑटोलेड होते हैं।

रूटिंग परिभाषा फ़ाइल में, आप उपयोग कर सकते हैं:

test:
    pattern:   /test
    defaults:  { _controller: Controller\Test::test }

यह किसी भी सादे पुराने php ऑब्जेक्ट हो सकता है, केवल इस तथ्य से फ्रेमवर्क से बंधा हुआ है कि उसे एक Symfony\Component\HttpFoundation\Responseऑब्जेक्ट वापस करना है।

आपके टहनी टेम्पलेट (या अन्य) को पसंद किया app/Resources/views/template.html.twigजा सकता है और इसे ::template.html.twigतार्किक नाम का उपयोग करके प्रदान किया जा सकता है ।

सभी DI सेवाओं को ऐप / config / config.yml में परिभाषित किया जा सकता है (या app/config/services.ymlउदाहरण के लिए आयात किया जा सकता है, और सभी सेवा वर्ग किसी भी सादे पुराने php ऑब्जेक्ट हो सकते हैं। फ्रेमवर्क से बिल्कुल भी बंधा हुआ नहीं है।

यह सब सिम्फनी पूर्ण स्टैक फ्रेमवर्क द्वारा डिफ़ॉल्ट रूप से प्रदान किया जाता है।

जहां आपको समस्याएं होंगी, जब आप अनुवाद फ़ाइलों (जैसे xliff) का उपयोग करना चाहेंगे, क्योंकि वे केवल बंडलों के माध्यम से खोजे जाते हैं ।

सिम्फोनी प्रकाश वितरण उद्देश्य सब कुछ है कि आमतौर पर केवल बंडलों के माध्यम से खोज की जा होगा की खोज द्वारा समस्याओं के इन तरह हल करने के लिए।


5

आप KnpRadBundle का उपयोग कर सकते हैं , जो प्रोजेक्ट संरचना को सरल बनाने की कोशिश करता है।

एक अन्य दृष्टिकोण src/Company/Bundle/FrontendBundleबंडलों के लिए और src/Company/Stuff/Class.phpउन वर्गों के लिए उपयोग करना है जो सिम्फनी स्वतंत्र हैं और जिन्हें फ्रेमवर्क के बाहर पुन: उपयोग किया जा सकता है।


लेकिन फिर मैं आवेदन को KnpRadBundle में युग्मित करूंगा ... क्या इस मामले पर कोई आसान तरीका नहीं है?
डेनियल रिबेरो

1
वे भाग जो सिम्फनी पर निर्भर करते हैं (नियंत्रक, मॉडल, टेम्प्लेट, आदि ...) हमेशा सिम्फनी के लिए जोड़े जाएंगे, क्योंकि आप इसका उपयोग कर रहे हैं (कक्षाओं का विस्तार, हेल्पर्स का उपयोग करके, आदि ...)। अकेले काम करने वाले वर्ग कंपनी के नामस्थान में होंगे, और आप उन्हें निर्भरता कंटेनर का उपयोग करके लोड कर सकते हैं। ये वर्ग स्वतंत्र हो सकते हैं।
मिगुएल_बाइरो

1
बात यह है कि, Bundleसार्वजनिक रूप से साझा करने पर अवधारणा सीधे चलती है। जब मैं कुछ एप्लिकेशन लिखता हूं, तो मैं अपने कोड को साझा नहीं करना चाहता, सिवाय उन हिस्सों को छोड़कर, जिन्हें मैंने जानबूझकर समुदाय-संचालित मॉड्यूल के रूप में बनाया था। क्या मै गलत हु?
डेनियल रिबेरो

आपको बंडलों को साझा करने की आवश्यकता नहीं है। कुछ विन्यास के साथ कक्षाओं के समूह के रूप में एक बंडल के बारे में सोचो। प्रत्येक परियोजना में आपके पास अलग-अलग बंडल हो सकते हैं।
मिगेल_बाइरो

आपको
सिम्फनी

5

चूंकि यह 5 साल पहले ही बीत चुका है, इसलिए यहां सिम्फनी बंडल्स के बारे में कुछ और लेख हैं।

  1. सिम्फनी में बंडलों क्या हैं? इल्तार वैन डेर बर्ग द्वारा।

TLDR:

क्या आपको सीधे अपने आवेदन में कई बंडलों की आवश्यकता है? न होने की सम्भावना अधिक। आप आश्रितों के एक स्पेगेटी को रोकने के लिए AppBundle लिखना बेहतर समझते हैं। आप बस सर्वोत्तम प्रथाओं का पालन कर सकते हैं और यह ठीक काम करेगा।

  1. सिम्फनी: टोनी Uebernickel द्वारा बंडल कैसे करें

TLDR:

अपने आवेदन तर्क के लिए AppBundle नामक केवल एक बंडल बनाएं। एक AppBundle - लेकिन कृपया अपने आवेदन तर्क को वहां न रखें!


-2

सिम्फनी फ्रेमवर्क बहुत अच्छी तरह से अवधारणा के प्रमाण को लॉन्च करने के लिए बहुत अच्छा है और सभी कोड src / में डिफ़ॉल्ट बंडल एप्लिकेशन के भीतर दर्ज कर सकते हैं

इस बंडल में आप अपना कोड स्ट्रक्चर कर सकते हैं जैसा आप चाहते हैं।

यदि आप अपनी POC विकसित करने के लिए अन्य तकनीक का उपयोग करना चाहते हैं, तो आप आसानी से इसका अनुवाद कर सकते हैं क्योंकि आप बंडल गर्भाधान में अपने सभी कोड की संरचना नहीं करते हैं।

अवधारणा के सभी के लिए आप इस चरम नहीं है। बंडल अच्छा है लेकिन हर चीज को बंडल करें और हर रोज अच्छा नहीं है।

बंडल थर्ड-पार्टी के प्रभाव को कम करने के लिए आप अपने प्रूफ ऑफ कॉन्सेप्ट को विकसित करने के लिए एक सिलेक्स (सिम्फनी माइक्रो फ्रेमवर्क) का उपयोग कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.