Eval jest zły
Po pierwsze:nie używaj eval()
chyba że istnieje dobry powód. I nigdy nie ma dobrego powodu .
w najgorszym przypadku eval()
sprawia, że Twoja aplikacja jest podatna na ataki wstrzykiwania, a także jest bardzo powolna. Trochę badań ujawnia wiele powodów, dla których ewaluacja jest wielkim nie-nie.
Nie zapisuj swojego kodu obliczeniowego w bazie danych
Jeśli to zrobisz i chcesz przełączyć się z PHP na inny język, nadal będziesz mieć kod PHP w swojej bazie danych. To bardzo utrudnia migrację języków. Zawsze powinieneś starać się, aby jak najwięcej części swojej aplikacji było jak najbardziej niezależnych.
W takim przypadku należy ściśle powiązać używany język z bazą danych. To zła praktyka.
Jedyną możliwością uruchomienia obliczeń z bazy danych byłoby również ich oszacowanie (co jest złe, patrz wyżej) lub rozłożenie łańcucha za pomocą operacji na łańcuchu lub wyrażenia regularnego, co powoduje niepotrzebny wysiłek.
Chodzi o Strategię
Aby rozwiązać swój problem, musisz wykonać kod zależny od potrzebnych obliczeń. Można to zrobić za pomocą instrukcji switch-case-statements lub if-statements. Ale to też nie jest zbyt eleganckie rozwiązanie. Wyobraź sobie, że musisz wykonać inne operacje przed obliczeniami w przyszłości lub rozszerzyć funkcjonalność. Będziesz musiał zaktualizować wszystkie swoje przypadki lub oświadczenia warunkowe.
Istnieje ładny wzór projektu, który nazywa się Wzorzec strategii . Wzorzec strategii rozwiązuje problemy, gdy jeden przypadek użycia może być obsłużony inaczej, co prawdopodobnie jest tym, czego chcesz.
Chcesz coś obliczyć (przypadek użycia) i istnieją różne typy obliczeń (różne strategie)
Jak to działa
Aby zaimplementować wzorzec Strategia, potrzebujesz trzech rzeczy.
- Zajęcia, w których wprowadzasz swoje strategie. To w zasadzie opakowanie dla twoich zadań strategicznych.
- Interfejs, który zostanie zaimplementowany przez Twoje strategie
- Twoje strategie
Twój interfejs może wyglądać tak:
<?php
interface CalculatableInterface {
public function calculate();
}
Interfejs zapewni, że wszystkie Twoje strategie zapewnią metodę rzeczywistego przeprowadzenia obliczeń. Nic specjalnego.
Następnie możesz chcieć mieć klasę bazową, która pobiera operatory obliczeń jako argumenty konstruktorów i przechowuje je we właściwościach.
<?php
abstract class Calculatable {
protected $valueA;
protected $valueB;
public function __construct($valueA, $valueB)
{
$this->valueA = $valueA;
$this->valueB = $valueB;
}
}
Teraz robi się poważnie. Wdrażamy nasze strategie.
<?php
class Division extends Calculatable implements CalculatableInterface {
public function calculate()
{
return ($this->valueB != 0) ? $this->valueA / $this->valueB : 'NA';
}
}
class Percentage extends Calculatable implements CalculatableInterface {
public function calculate()
{
return ($this->valueB != 0) ? (100 / $this->valueB) * $this->valueA : 'NA';
}
}
Oczywiście możesz to trochę posprzątać, ale chciałbym tutaj zwrócić uwagę na deklarację klasy.
Rozszerzamy naszą Calculatable
klasy, dzięki czemu możemy przekazać operacje arytmetyczne przez konstruktor i implementujemy CalculatableInterface
który mówi naszej klasie:„Hej! Musisz podać metodę obliczania, nie obchodzi mnie, czy chcesz, czy nie.
Zobaczymy później, dlaczego jest to integralna część wzorca.
Mamy więc dwie konkretne klasy, które zawierają rzeczywisty kod dla rzeczywistej operacji arytmetycznej. Jeśli kiedykolwiek będziesz potrzebować, możesz to łatwo zmienić, jak widzisz.Aby dodać więcej operacji, po prostu dodaj kolejną klasę.
Teraz stworzymy klasę, do której będziemy mogli wstrzykiwać nasze strategie. Później utworzysz instancję obiektu tej klasy i będziesz z nim pracować.
Oto jak to wygląda:
<?php
class Calculator {
protected $calculatable;
public function __construct( CalculatableInterface $calculatable )
{
$this->calculatable = $calculatable;
}
public function calculate()
{
return $this->calculatable->calculate();
}
}
Najważniejszą częścią jest tutaj konstruktor. Zobacz, jak piszemy w naszym interfejsie tutaj. Robiąc to, upewniamy się, że tylko obiekt może zostać wstrzyknięty (Wstrzykiwanie zależności ), którego klasa implementuje interfejs . Nie potrzebujemy tutaj konkretnej klasy. To jest tutaj kluczowy punkt.
Jest tam również metoda obliczeniowa. To tylko opakowanie dla naszej strategii, aby wykonać metodę obliczeniową.
Zawijanie
Więc teraz musimy tylko stworzyć obiekt naszego Calculator
i przekazać obiekt jednej z naszych klas strategii (zawierających kod dla operacji arytmetycznych).
<?php
//The corresponding string is stored in your DB
$calculatable = 'Division';
$calc = new Calculator( new $calculatable(15, 100) );
echo $calc->calculate();
Spróbuj zastąpić ciąg przechowywany w $calculatable
na Percentage
i zobaczysz, że operacja obliczania wartości procentowej zostanie wykonana.
Wniosek
Wzorzec strategii umożliwił stworzenie przejrzystego interfejsu do pracy z zadaniami dynamicznymi, które są skonkretyzowane tylko w czasie wykonywania. Ani Twoja baza danych nie musi wiedzieć, jak obliczamy rzeczy, ani Twój rzeczywisty kalkulator. Jedyne, czego musimy się upewnić, to kodowanie w interfejsie która zapewnia metodę pozwalającą nam obliczyć rzeczy.