Soru Symfony2 - Denetleyicide __construct () nasıl kullanılır ve Securty.Context dosyasına nasıl erişilir?


Symfony2 ile sorun yaşıyorum. Yani __construct () işlevinin nasıl kullanılacağı. Resmi Belgeler şok edici derecede kötü!

Aşağıdakileri kullanmak istiyorum:

public function __construct()
{
    parent::__construct();
    $user = $this->get('security.context')->getToken()->getUser();
}

Aşağıdaki hatayı nasıl alırım:

Önemli hata: Satır 11'de /sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php dosyasında yapıcı çağrılmıyor

11. satır "parent :: __ construct ();"

Onu kaldırdım ve aşağıdaki, yeni hatayı aldım

Ölümcül hata: 242 numaralı hatta /Sites/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php adresindeki nesne olmayan bir öğe işlevine get () işlevi çağrısı

ben düşünmek ContainerInterface DIC'yi kurmam gerekebilir, ancak bunu nasıl yapacağımı bilmiyorum (denedim ve başarısız oldum, sefil bir şekilde)

Herhangi bir fikir millet?

Güncelleştirme - ContainerAware'i genişletmek için değişiklik yaptım ve şu hatayı aldım:

Önemli hata: Sınıf DEMO \ DemoBundle \ Controller \ Frontend \ HomeController, 43. satırdaki /Sites/src/DEMO/DemoBundle/Controller/Frontend/HomeController.php içindeki Symfony \ Component \ DependencyInjection \ ContainerAwareInterface arabiriminden genişletilemiyor

Denetleyicide aşağıdaki kodu kullanarak:

<?php

namespace DEMO\DemoBundle\Controller\Frontend;

use Symfony\Component\DependencyInjection\ContainerAware;

class HomeController extends ContainerAwareInterface
{
     protected $container;

     public function setContainer(ContainerInterface $container = null)
     {
         $this->container = $container;
     }

18
2018-03-16 11:42


Menşei


Bence kabine __construct'a erişemezsin. - gremo
Neden basitçe kullanıcı örneğini yapıcıda bir argüman olarak enjekte etmiyorsunuz? - Nanocom
Denetleyicimde yeniden kullanabileceğim bazı değişkenler belirlememe izin vermek için __construct () veya benzer bir özellik kullanabilmek istiyorum. CodeIgniter2'de, herhangi bir problemi çözebilirim, fakat Symfony2 oldukça farklıdır ve çok basit bir şey elde etmek için yaklaşık 20 adım atmam gerekiyor (ya da durum böyle değil) - Mr Pablo
Sadece ContainerAware kullanmak yerine kurucudaki kabı enjekte edin. (Kontrol cihazınızı servis olarak tanımlayın). - Florian
Ayrıca "extends" yerine "implements" anahtar sözcüğünü kullanmak istiyorsunuz. Sınıf genişletilir, arayüzler uygulanır. - Thomas K


Cevaplar:


Varsayılan Symfony kontrol cihazını uzattığını mı varsayıyorum? Eğer öyleyse, koda bir bakış cevabı ortaya çıkaracaktır:

namespace Symfony\Bundle\FrameworkBundle\Controller;

use Symfony\Component\DependencyInjection\ContainerAware;

class Controller extends ContainerAware
{

Herhangi bir Controller :: __ yapısının bulunmadığına dikkat edin, böylece parent :: __ yapısını kullanarak herhangi bir yere ulaşamazsınız. ContainerAware'e bakarsak:

namespace Symfony\Component\DependencyInjection;

class ContainerAware implements ContainerAwareInterface
{
    protected $container;
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}

Yine, setContainer çağrılıncaya kadar hiçbir kurucu ve konteyner kullanılamaz. Bu yüzden setContainer'ı geçersiz kılın ve mantığınızı buraya yerleştirin. Ya da sadece temel denetleyici sınıfını genişletmeyen ve bağımlılıklarınızı doğrudan kurucuya enjekte etmeyen bağımsız bir denetleyici yapın.

2017 Güncellemesi

Hala bunun üzerine birkaç isabet aldım. Her denetleyiciden önce gerçekten bir şey yürütmek istiyorsanız, o zaman bir çekirdek denetleyicisi dinleyicisi kullanın. İhtiyacınız olan tek şey kullanıcı ise elbette getUser () kullanın. Ve lütfen setContainer () öğesini geçersiz kılmayın. Bazı durumlarda işe yarayacaktı ama sadece kodunuzu dolaştırırdı.


23
2018-03-16 13:38



Denetleyiciyi uzatabilir ve setContainer'ı geçersiz kılabilir miyim, yoksa ContainerAware veya ContainerAwareInterface'i genişletmem gerekir mi? - Mr Pablo
Controller ve setContainer'ı genişletebilirsiniz. Ama bence bir getUser () yöntemi eklemekten daha iyi olabileceğinizi göreceksiniz. Akışla devam edin ve CI deneyiminizden çok fazla şey uygulamaya başlamadan önce Symfony yolunda çalışın. - Cerad
Temel yöntemleri kullanabilirim, ancak her bir Eylem için kodu tekrarlamam gerekiyor olabilir. Nihayetinde, her bir denetleyici için bir değişken üzerinde bir kontrol yapmak için bir yol bulmak istedim, bu yüzden kopya ve kod parçalarını yapıştırmak yerine, bir parça alabilir ve HER denetleyicinin çağrıldığını her seferinde çalıştırabilirim. - Mr Pablo


Ayrıca çoğu zaman denetleyicilerimin çoğunda geçerli Kullanıcı örneğini istiyorum. Bunun gibi bir şey yapmanın en kolay olduğunu düşünüyorum:

class SomeController extends Controller
{
    protected $user;

    public function getUser()
    {
        if ($this->user === null) {
            $this->user = $this->get('security.context')->getToken()->getUser();
        }
        return $this->user;
    }
}

Ancak, bu çok basit bir örnek durumdur. Bir Denetleyici eylemi başlatılmadan önce daha fazla iş yapmak istiyorsanız, sizi öneririm Denetleyicinizi Servis olarak tanımlayın.

Ayrıca bu makaleye bir göz atın: Baz Kontrolcüsünden Uzaklaşmak


4
2018-03-17 19:02



Merhaba, simfony 2.1'de getUser yöntemi Controller'ın bir parçası gibi görünüyor. - Yann Sagon
Her iki link de öldü. - BetaRide
Sabit! Teşekkürler @BetaRide - leek


Geri kalan api'nin kaynağı için 'cephe' yöneticisini almalıyım. Kurucuyu kullanmamak ve özel bir işlev kullanmak benim için en kolay ve en basit gibi görünüyor.

/**
 * Class ExchangesController
 * @RouteResource("Exchange")
 */
class ExchangesController extends Controller
{
    /**
     * Get exchange manager
     * @return ExchangeManager
     */
    protected function getExchangeManager()
    {
        return $this->get('exchange_manager');
    }

    /**
     * @ApiDoc(
     *  description="Retrieve all exchanges",
     *  statusCodes={
     *    200="Successful"
     *  }
     * )
     */
    public function cgetAction()
    {
        return $this->getExchangeManager()->findAll();
    }

PS Sıfır koşullu olduğu sürece denetleyicimde özel / korumalı işlevleri kullanmam uygun


1
2017-07-03 12:02



Özel / Korumalı yöntemler denetleyiciye ait değildir. Bunu yapıyorsan yanlış olduğunu söylemiyorum ama her zaman bir şeyler yapmanın daha iyi bir yolu var. - tomazahlin
@tomazahlin Sanırım seninle aynı fikirdeyim, şimdi Denetleyiciyi bu yöntemlerle genişleten bir BaseController yaratmayı tercih ederim. O zaman yeterince iyi bir çözümdü. Geçen sene uzun bir yol katettim. - Tjorriemorrie


Denetleyici kurucularındaki hizmetler için getUser () veya get () yöntemini çağıramazsınız. Bunu hatırlarsanız, birçok hata ayıklama zamanından tasarruf edersiniz.


0
2018-04-21 21:53



Herhangi bir sebep var mı? Talebinizi yedeklemek için herhangi bir belge var mı? Lütfen. - Nis


Sorunun çok eski olduğunu biliyorum ama şu ana kadar bir cevap bulamadım. Bu yüzden paylaşacağım.

Buradaki amaç, denetleyicimizdeki her hareketin çağrıldığı bir kod yürütmektir.

__construct yöntem işe yaramıyor, çünkü başka bir şeyden önce çağrılıyor, bu yüzden servis kabına erişemiyorsunuz.

Hile, çağrıldıklarında her yöntemi otomatik olarak yüklemektir:

<?php
namespace AppBundle\DefaultController;

class DefaultController extends Controller {
    private function method1Action() {
        return $this->render('method1.html.twig');
    }

    private function method2Action() {
        return $this->render('method2.html.twig');
    }

    public function __call($method, $args) {
         $user = $this->get('security.tokenStorage')->getToken()->getUser();

         // Do what you want with the User object or any service. This will be executed each time before one of those controller's actions are called.

        return call_user_func_array(array($this, $method), $args);
    }
}

Uyarı! Her yöntemi özel bir yöntem olarak tanımlamanız gerekir! Ya da __call sihirli yöntem çağrılmayacak.


0
2018-04-22 09:32





Bu soruna sadece iki çözüm var:

  1. @Tjorriemorrie tarafından işaret edildiği gibi özel bir yöntem kullanın İşte. Fakat bu, püristler için kirli bir yöntem. (Bunu kullanıyorum!: D);

  2. Denetleyiciyi bir hizmet olarak tanımlayın, ancak bu şekilde sağlanan tüm kısayolları kaybedersiniz. Symfony\Bundle\FrameworkBundle\Controller\Controller. İşte Bunu nasıl yapacağınızı gösteren makale.

Şahsen, söylediğim gibi, benim durumumda böyle bir çözüm öneriyorum:

class MyController extends Controller
{
    /** @var AwesomeDependency */
    private $dependency;

    public function anAction()
    {
         $result = $this->getDependency();
    }

    /**
     * Returns your dependency.
     */
    private function getDependency()
    {
        if (null === $this->dependency)
            $this->dependency = $this->get('your.awesome.dependency');

        return $this->dependency;
    }
}

Bu genellikle aradığım bir sınıftır MyManager Birden fazla eylemde kullandığım veya denetleyicide kullandığım kodu koyduğum ya da (örneğin, çok sayıda kod gerektiren ağır görevleri veya görevleri yapmak için formları oluşturmak ve doldurmak için kod).

Böylelikle, koddaki eylemi, amaçlarına karışıklık katmadan, kendi amaçlarına göre temizlerim.

Belki de bağımlılığı depolamak için bir mülkün kullanımı bir overoptimizasyon, ama ... Ben bunu seviyorum :)


0
2017-11-09 22:17





Gördüğüm gibi, kontrolör uzanır ContainerAwareve eğer bir bakarsak ContainerAware uygular ContainerAwareInterface. Yani, ContainerAware Arayüzünde kesin yöntemleri açıklamış olmalı. Bu satırı ekle

genel işlev __construct ();

göre ContainerAwareInterface Tanım ve çözülecektir.


-3
2018-03-26 17:16