2011-08-29 6 views
7

W naszej bieżącej aplikacji Mam raport, który zawiera coś takiego:Jak mogę zapisać warunkową stację PHP w bazie danych do późniejszego wykorzystania?

if($foo == 3 || $bar > 3) { 
    $e = someFunction(); 
}; 

ale dla innego klienta, że ​​samo wyrażenie może być:

if($foo == 3 || $bar == 5 && $foobar != 9) { 
    $e = someFunction(); 
}; 

Czy istnieje prosta droga do zapamiętywania dwa różne wyrażenia, tylko

$foo == 3 || $bar > 3 OR $foo == 3 || $bar == 5 

bity w bazie danych (MySQL), więc nie trzeba ciężko kodem wszystkich tych zasad przez klienta lub utrzymywać wersje klienta tego samego raportu. Próbuję dowiedzieć się, czy mogę ustawić zmienną o zastąpić warunki. Coś takiego:

$conditions = $row_rsConditions['condition_row'] //Get $foo == 3 || $bar > 3 from the DB and store it as $conditions 
if($conditions) { 
    $e = someFunction(); 
}; 

Może być> 100 różnych klientów, a każdy klient może/miałby inny zestaw wyrażeń. Po prostu nie jestem pewien/najlepszego sposobu na zrobienie tego.

UPDATE:

myślę zrozumieć problemy z wykorzystaniem PHP funkcji eval(). Ale ze względu na liczbę możliwych kombinacji pochylam się, aby użyć DB do przechowywania warunków (nie jestem pewien, czy jeszcze użyć eval()).

Czy to ma znaczenie (bezpieczniejsze), jeśli nie ma interfejsu użytkownika zapisuje do pola warunków/tabeli? To może być coś, na co sami sobie poradzimy.

+4

Co powiesz na zapisanie kodu do bazy danych, a później załadowanie i wykonanie za pomocą 'eval' ? Możliwe, że pojawią się problemy z bezpieczeństwem, gdy ktoś wstrzyknie bazę danych i zmusi cię do oceny swojego kodu. – Nobody

+0

Następnie pojawia się pytanie, w jakich okolicznościach operatorzy w warunkach mogą się zmienić? – Deele

+5

Myślę, że to bardzo zły projekt do przechowywania logiki w bazie danych, baza danych powinna być używana tylko dla danych – Fivell

Odpowiedz

3

Byłbym bardzo ostrożny w przechowywaniu logiki w bazie danych.

  1. Twój kod nie jest już w jednym miejscu.
  2. logika w bazie danych najprawdopodobniej nie będzie pod kontrolą źródła
  3. jeśli zmienisz kod i złamiesz całą logikę tego klienta, musisz wrócić do bazy danych i edytować ją dla każdego klienta.
  4. inne osoby mogły mieć dostęp do bazy danych i mogły zmienić kod na złośliwy.

To może nie być najlepsze rozwiązanie , ale proponuję utworzyć abstrakcyjną klasę bazową, a następnie dziedziczyć po niej klasę specyficzną dla każdego klienta.

Wszelkie niestandardowe funkcje można dodać jako metodę do klasy bazowej i zastąpić w celu implementacji konkretnego klienta.

użyj instrukcji switch, aby utworzyć instancję klasy na podstawie identyfikatora lub nazwy klienta (coś, co się nie zmienia), które już przechowujesz w bazie danych.

switch ($client_name) { 

case "abc ltd": 
    $customlogic = new CustomLogicAbc(); 
    break; 

case "zyx ltd": 
    $customlogic = new CustomLogicXyz(); 
    break; 

default: 
    $customlogic = new CustomLogicDefault(); 
    break; 

} 

if ($customlogic->doSomething($parm1, $parm2)) { 
    // custom logic has been applied 
} 
+0

Myślę, że problem jest stosunkowo prosty, co oznacza, że ​​sprawdza tylko te dwie wartości. Ale ma na sobie wiele różnych warunków, że wszystko będzie musiało być zakodowane. Zamiast tego parametryzacja wymagałaby tylko jednej implementacji i pobierania warunków w zależności od potrzeb. – Nobody

+0

Więc jeśli jest ponad 100 klientów, ta opcja jest nadal możliwa? Zgadzam się z punktami # 1 i # 2. # 3 jest na nas, aby utrzymać się prawidłowo i # 4 - jeśli mogą to zmienić, to mogą już zadać o wiele więcej obrażeń, prawda? – Jason

+0

To naprawdę zależy od tego, ile masz niestandardowej logiki i jak skomplikowana jest. Jeśli w twoim przykładzie pokazane jest tylko jedno wyrażenie, lepiej może być przechowywanie parametrów $ foo i $ bar w bazie danych dla każdego rekordu klienta, a nie samej faktycznej logiki. Jeśli masz dużo spersonalizowanych instrukcji i są one złożone, to zrobiłbym to, co zrobiłem powyżej, ponieważ szanse są logiczne, gdy tylko będziesz bardziej złożony, i dodasz więcej dostosowanych rzeczy. – bumperbox

2

Wypracowanie na mój komentarz:

Twój ostatni kod jest prawie co mam na myśli:

$conditions = $row_rsConditions['condition_row']; //Get "$foo == 3 || $bar > 3" 
if(eval("return (" . $conditions . ");")) { 
    $e = someFunction(); 
} 

Jednak będę cię ostrzec ponownie pamiętać ryzyko to robi. Podczas korzystania z kodu z bazy danych prawdopodobne jest, że błędy są w nim zawarte. Przynajmniej należy przeprowadzić kontrolę bezpieczeństwa danych, aby uniknąć niewłaściwego użycia.

Inną opcją, która jest nieco bardziej skomplikowana, ale nie tak podatna na niewłaściwe użycie, byłoby zakodowanie warunków. Jak się wydaje, że tylko porównać 2 zmiennych o wartości każdego można zapisać dla każdej zmiennej coś takiego:

0 != 
1 == 
2 >= 
3 <= 
4 > 
5 < 

Aby zapisać relację i dodatkowo zapisać wartości, które powinny być porównywane. W ten sposób nie ma bezpośredniej realizacji kodu, który jest zapisany w bazie danych.

+0

Wyjątkowo niebezpieczne! – Gustav

+0

@Gustav - Czy jest to niebezpieczne, ponieważ otwierałbym miejsce, aby umożliwić wstrzyknięcie kodu lub czy jest coś więcej? – Jason

+0

@Jason Część zastrzyku PHP jest najgorsza. – Gustav

0

nikt nie może powiedzieć, jak go rozwiązać, bo nikt nie wie, wymagania funkcjonalne i specyficzną logikę aplikacji ... Ale jeśli czas realizacji jest ważna dla ciebie można oczywiście próbować używać evaluationg wyrażeń z bazy danych, ale bądź ostrożny i używaj do czyszczenia wszystkich danych z bazy danych ... Istnieje przykład how to make php expressions and execute from database? - dodajesz więcej logiki, ponieważ możesz mnożyć warunki