2015-06-30 17 views
6

'da çalışmaya başlamadan önce denetleyici eylemini gerçekleştirme Yii2 denetleyicisindeki bazı kodları çalıştırmaya çalışıyorum Modelin bir parametre olarak geçiş yapabilmesi için modelden behaviors bölümüne erişebilmem için bazı kodları çalıştırmam gerekiyor yinelenen sorgular çalıştırmamak; ancak aynı zamanda action'un çağrıldığını da öğrenmem gerekiyor, ancak fazla şansım yok.Davranış kodu Yii2

Ben beforeAction kullanarak denedi ama bu beni yardımcı olmuyor yüzden, bu behaviours kod çalıştırır SONRA koþulur görünüyor.

init kullanmayı denedim, ancak action bu noktada $this->action->id aracılığıyla kullanılamaz.

Bazı örnek kodu:

class MyController extends Controller { 

    public $defaultAction = 'view'; 

    public function init() { 

     // $this->action not available in here 

    } 

    public function beforeAction() { 

     // This is of no use as this runs *after* the 'behaviors' method 

    } 

    public function behaviors() { 
     return [ 
      'access' => [ 
       'class' => NewAccessControl::className(), 
       'only' => ['view','example1','example2'], 
       'rules' => [ 
        [ 
         'allow' => false, 
         'authManager' => [ 
          'model' => $this->model, 
          'other_param' => $foo, 
          'other_param' => $bar, 
         ], 
         'actions' => ['view'], 
        ], 
        // everything else is denied 
       ], 
      ], 
     ]; 
    } 

    public function viewAction() { 

     // This is how it is currently instantiated, but we want to instantiate *before* the behavior code is run so we don't need to instantiate it twice 
     // but to be able to do that we need to know the action so we can pass in the correct scenario 

     $model = new exampleModel(['scenario' => 'view']); 

    } 

} 

authManager sadece AccessRule sınıfının bir uzantısı içinde bir member variable başvurusudur.

Yine de yapabilir miyim?

+0

numaralı telefonu arayın * AccessControll * 'matchCallback' veya bazı özel davranışlardan bahsediyor musunuz? – Tony

+0

@Tony Bu soruyu yayınladığımdan beri, işlerimi nasıl değiştirdiğimi değiştirdim, ancak yine de modeli 'davranışlar' bölümündeki koddan erişebilmem gerekiyor, bu yüzden modeli bir parametre olarak iletebilir ve yinelenen çalışmayı önleyebilirim sorguları. Sorumu güncelleyeceğim. – Brett

cevap

9

Eh, seni doğru alırsanız, böyle bir şey arıyorsanız: Sadece bir yöntemdir

public function behaviors() 
{ 
    $model = MyModel::find()->someQuery(); 
    $action = Yii::$app->controller->action->id; 
    return [ 
     'someBehavior' => [ 
      'class' => 'behavior/namespace/class', 
      'callback' => function() use ($model, $action) { 
       //some logic here 
      } 
     ] 
    ]; 
} 

behaviors() olduğundan, herhangi değişkenleri bildirmek ve içinde istediğiniz herhangi mantığı ekleyebilir İzlemeniz gereken yalnızca bir kural - bu dönüş türünün dizisi olması gerekir.

Özel davranışınızı kullanırsanız, davranışınızın yöntemlerini belirli olaylara bağlayabileceğiniz events() yöntemini kullanabilirsiniz. Örneğin. Kullanıcı başarıyla uygulamaya giriş sonra bu örnekte myAfterLoginEvent yılında

class MyBehavior extends Behavior 
{ 
    public function events() 
    { 
     return [ 
      \yii\web\User::EVENT_AFTER_LOGIN => 'myAfterLoginEvent', 
     ]; 
    } 

    public function myAfterLoginEvent($event) 
    { 
     //dealing with event 
    } 
} 

çalıştırılacaktır. $event değişken çerçeve tarafından geçirilecek ve olay türüne bağlı olarak farklı veriler içerecektir. about event object

GÜNCELLEME Oku: Şimdi görebileceğiniz gibi

cevabım olayları ve davranışları hakkında daha genel. Eğer kod eklendiğinde Ve şimdi, aşağıdaki kodla davranışınbeforeAction($action) yöntemini geçersiz kılmak için size önerebilir:

public function beforeAction($action) 
{ 
    $actionID = $action->id; 
    /* @var $rule AccessRule */ 
    foreach ($this->rules as &$rule) { 
     $model = &$rule->authManager['model']; 
     //now set model scenario maybe like this 
     $model->scenario = $actionID; 
    } 
    //now call parent implementation 
    parent::beforeAction($action); 
} 

Ayrıca AccessControlimplementation of beforeAction yöntemine bakmak, her kural allows yöntemiyle için çağırır Geçerli eylemi parametre olarak geçirir. Bu nedenle, AccessRule'u genişleten bir sınıfınız varsa, uygun model senaryosunu ayarlamak için izinlerini ($ eylem, $ kullanıcı, $ istek) yöntemini veya matchCustom($action) yöntemini geçersiz kılabilirsiniz. Umarım bu yardımcı olur.

bir daha alternatif:

geçersiz kılma denetleyicisinin runAction($id, $params = []) yöntemi. Burada $ id actionID - tam olarak ihtiyacınız olan şey.Kimliği kontrol edin, uygun model senaryosunu ayarlayın ve parent::runAction($id, $params);

+0

Modelleri 'davranış' yönteminde başlatmaktan kaçınmak istediniz çünkü normalde modellerinizi orada başlatmayı beklemiyorsunuz ve işleri olabildiğince organize etmeye çalışıyorum. Temel olarak benim durumum şu: Modelleri denetleyicideki tüm 'eylem' yöntemleri içinde örneklendiriyorum, bunların hepsi modele aktarılan farklı bir senaryo kullanıyor. Bu nedenle, modelin eylem yöntemlerinin dışına çıkarılması gerektiğinden, modelin 'eylemi' bilmem gereken davranış kodu içinde bir param olarak geçebilmesi için doğru senaryoyu geçebilmem gerekir. – Brett

+0

Eylemi 'Yii :: $ app-> controller-> action-> id' – Tony

+0

ile alabilirsiniz. Biliyorum, ama init' yönteminde henüz mevcut değil. – Brett