Eval je zlo
Za prvé:nepoužívejte eval()
pokud k tomu není dobrý důvod. A nikdy neexistuje dobrý důvod .
v nejhorším případě eval()
dělá vaši aplikaci zranitelnou vůči injekčním útokům a také je velmi pomalá. Trochu výzkumu odhaluje spoustu důvodů, proč je eval velké ne-ne.
Neukládejte výpočetní kód do databáze
Pokud tak učiníte a chtěli byste přejít z PHP na jiný jazyk, stále byste měli kód PHP ve své databázi. To velmi ztěžuje migraci jazyků. Vždy byste se měli snažit, aby co nejvíce částí vaší aplikace bylo co nejvíce nezávislých.
V tomto případě byste jazyk, který používáte, těsně spojili s databází. To je špatná praxe.
Jedinou možností, jak spouštět výpočty z databáze, by bylo také jejich vyhodnocení (což je špatné, viz výše) nebo rozebrání řetězce pomocí operací s řetězci nebo regulárního výrazu, což způsobuje zbytečné úsilí.
Vše je o strategii
Abyste vyřešili svůj problém, musíte spustit kód v závislosti na tom, jaký výpočet potřebujete. To lze provést buď pomocí příkazů switch-case nebo if. Ale to také není příliš elegantní řešení. Představte si, že byste před výpočtem v budoucnu museli provést další operace nebo rozšířit funkčnost. Budete muset aktualizovat všechny své případy nebo prohlášení if.
Existuje pěkný designový vzor, který se nazývá Vzor strategie . Vzor strategie řeší problémy, kdy lze jeden případ použití řešit jinak, což je pravděpodobně to, co chcete.
Chcete něco vypočítat (případ užití) a existují pro to různé typy výpočtů (různé strategie)
Jak to funguje
K implementaci strategie strategie potřebujete v podstatě tři věci.
- Kurz, kde aplikujete své strategie. Je to v podstatě obal pro vaše strategické úkoly.
- Rozhraní, které bude implementováno vašimi strategiemi
- Vaše strategie
Vaše rozhraní může vypadat takto:
<?php
interface CalculatableInterface {
public function calculate();
}
Rozhraní zajistí, že všechny vaše strategie poskytují metodu skutečného spuštění výpočtu. Nic zvláštního.
Dále možná budete chtít mít základní třídu, která vezme vaše výpočetní operátory jako argumenty konstruktoru a uloží je do vlastností.
<?php
abstract class Calculatable {
protected $valueA;
protected $valueB;
public function __construct($valueA, $valueB)
{
$this->valueA = $valueA;
$this->valueB = $valueB;
}
}
Teď to začíná být vážné. Implementujeme naše 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';
}
}
Samozřejmě byste to mohli trochu vyčistit, ale na co zde chci upozornit, je deklarace třídy.
Rozšiřujeme naše Calculatable
třídy, abychom mohli předávat aritmetické operace přes konstruktor a implementujeme CalculatableInterface
což naší třídě říká:"Hej! Musíte poskytnout metodu výpočtu, je mi jedno, jestli chcete nebo ne."
Později uvidíme, proč je toto nedílnou součástí vzoru.
Máme tedy dvě konkrétní třídy, které obsahují skutečný kód pro skutečnou aritmetickou operaci. Pokud byste to někdy potřebovali, můžete to snadno změnit, jak vidíte. Chcete-li přidat další operace, přidejte další třídu.
Nyní vytvoříme třídu, do které lze aplikovat naše strategie. Později vytvoříte instanci objektu této třídy a budete s ním pracovat.
Takto to vypadá:
<?php
class Calculator {
protected $calculatable;
public function __construct( CalculatableInterface $calculatable )
{
$this->calculatable = $calculatable;
}
public function calculate()
{
return $this->calculatable->calculate();
}
}
Nejdůležitější částí je zde konstruktor. Zde se podívejte, jak píšeme naše rozhraní. Tím zajistíme, že může být vstříknut pouze objekt (Injekce závislosti ), jehož třída implementuje rozhraní . Nemusíme zde vyžadovat konkrétní třídu. To je klíčový bod.
Je tam také metoda výpočtu. Je to jen obal pro naši strategii k provedení metody výpočtu.
Zabalím to
Takže teď už jen potřebujeme vytvořit objekt naší Calculator
a předat objekt jedné z našich strategických tříd (které obsahují kód pro aritmetické operace).
<?php
//The corresponding string is stored in your DB
$calculatable = 'Division';
$calc = new Calculator( new $calculatable(15, 100) );
echo $calc->calculate();
Zkuste nahradit řetězec uložený v $calculatable
na Percentage
a uvidíte, že operace pro výpočet procenta bude provedena.
Závěr
Vzor strategie vám umožnil vytvořit čisté rozhraní pro práci s dynamickými úkoly, které se konkretizují až za běhu. Ani vaše databáze nemusí vědět, jak věci počítáme, ani vaše skutečná kalkulačka to neví. Jediné, co se musíme ujistit, je kódování proti rozhraní který poskytuje metodu, jak věci vypočítat.