2012-07-09 7 views
6

Mam dwa połączenia z bazą danych, jeden używany dla większości moich danych aplikacji i taki, który jest używany tylko do odczytu.Yii ogranicza połączenie z bazą danych tylko do odczytu

Mimo że mogę skonfigurować moje konto użytkownika bazy danych, aby zezwalać tylko na odczyty, istnieją inne osoby administrujące tym systemem i chcę pewnej redundancji na poziomie aplikacji, aby absolutnie zapobiec niezamierzonym zapisom przy użyciu standardowych klas ActiveRecord Yii.

Znalazłem tę informację na forach, ale zastanawiałem się, czy ktoś może potwierdzić, że jest to dobre podejście i/lub zasugerować inną.

public function onBeforeSave($event) 
{ 
    $this->db = Yii::app()->masterDb; 
} 

public function onAfterSave($event) 
{ 
    $this->db = Yii::app()->db; 
} 

http://www.yiiframework.com/forum/index.php/topic/5712-active-record-save-to-different-server-load-balancefail-over-setup/

+2

Użycie oddzielnego użytkownika bazy danych to rozsądna droga. –

+1

@ tereško ... i jedyny sposób, aby w pełni zagwarantować, że żaden przyszły kod nie złamie tej "konwencji" ... – Ron

+0

Zgadzam się, że użytkownik tylko do odczytu DB jest najbardziej eleganckim rozwiązaniem, jednak chcę nadmiarowości, ponieważ nie ufam ludziom administrowanie systemem 100% –

Odpowiedz

4

za ten link podany na forach Yii jest rozszerzeniem, które obsługuje to dla Ciebie: http://www.yiiframework.com/extension/dbreadwritesplitting

bym pewnie patrzeć, że po pierwsze, jeśli masz mam wiele modeli AR. Możesz pójść drogą Zachowania (zgodnie z sugestią tego postu na forum) jako inną opcją.

Ale cokolwiek robisz, będziesz chciał nadpisać przed zapisaniem/zachowaniem, zamiast przed zapisaniem w pamięci podręcznej/zapisywaniu po operacji. Te metody służą do wyzwalania zdarzeń, a nie tylko do uruchamiania własnego kodu specjalnego. I, na another one of the forum posts, musisz ustawić zmienną AR db przy użyciu połączenia statycznego. Więc kod Siergieja powinien być:

class MyActiveRecord extends CActiveRecord 
{ 
    ... 
    public function beforeSave() 
    { 
     // set write DB 
     self::$db = Yii::app()->masterDb; 

     return parent::beforeSave(); 
    } 

    public function afterSave() 
    { 
     // set read db 
     self::$db = Yii::app()->db; 

     return parent::beforeSave(); 
    } 
    ... 
} 


class User extends MyActiveRecord {} 
class Post extends MyActiveRecord {} 
... 
+0

To rozszerzenie jest całkiem fajne, będę musiał przeczytać trochę więcej na ten temat. –

2
class MyActiveRecord extends CActiveRecord 
{ 
... 
public function onBeforeSave($event) 
{ 
    // set write DB 
    $this->db = Yii::app()->masterDb; 
} 

public function onAfterSave($event) 
{ 
    // set read db 
    $this->db = Yii::app()->db; 
} 
... 
} 


class User extends MyActiveRecord {} 
class Post extends MyActiveRecord {} 
... 

U spróbować w ten sposób :) Ale IMHO to nie jest wystarczająco dobre. Myślę, że będą jakieś błędy lub wady

+0

Dziękuję za umieszczenie w części tego rozwiązania, które opuściłem z mojego postu, dla przyszłego odniesienia dla każdego, kto ogląda to pytanie. Jakiego rodzaju błędów/wad odnoszą się do? –

+0

@JohnZ, acorncom mówi: 'onBeforeSave/onAfterSave. Te metody służą do wyzwalania zdarzeń, a nie tylko do uruchamiania własnego specjalnego kodu ". To znaczy. – Sergey

2

Biorąc pod uwagę scenariusz, w którym twój niewolnik nie może aktualizować się z mistrzem, możesz napotkać problemy. Ponieważ po aktualizacji danych możesz przeczytać ze starej wersji.

Podczas gdy podane podejścia na forum są bardzo przejrzyste i napisane przez autorów, którzy w większości są magami Yii. Mam też alternatywę. Możesz zastąpić metodę getDbConnection() w AR podobną do:

public function getDbConnection(){ 
    if (Yii::app()->user->hasEditedData()) { # you've got to write something like this(!) 
    return Yii::app()->masterDb; 
    } else { 
    return Yii::app()->db; 
    } 
} 

Mimo to musisz zachować ostrożność podczas przełączania połączeń z bazą danych.