Odporúčané postupy
Táto sekcia uvádza odporúčané postupy pri vývoji modulov a aplikácií s DotApp PHP Framework. Ich dodržiavaním zabezpečíte, že vaše moduly budú prenosné, zdieľateľné medzi aplikáciami a prispôsobivé akejkoľvek konfigurácii servera vrátane rôznych ovládačov session (napríklad Redis, súborový, databázový) a databázových ovládačov (PDO, MySQLi). Dodržiavanie filozofie frameworku zaručí konzistentné výstupy bez ohľadu na použité ovládače.
Prehľad filozofie
Framework DotApp je navrhnutý na tvorbu prenosných a udržiavateľných modulov, ktoré bezproblémovo fungujú v rôznych prostrediach. Dodržiavaním týchto postupov sa vaše moduly prispôsobia ovládaču session používateľa (napríklad Redis, databáza) aj databázovému ovládaču (PDO, MySQLi) bez zmeny kódu. Aplikácia tak ostane flexibilná a zdieľateľná, v súlade so základnou filozofiou DotApp: modularitou a prispôsobivosťou.
Kľúčovým aspektom filozofie DotApp je bezpečnosť vstupov. Predvolene sú všetky vstupy automaticky chránené pred bežnými zraniteľnosťami, napríklad Cross-Site Scripting (XSS). Tento návrh drží aplikáciu v bezpečí aj vtedy, keď sa na jeden vstup zabudne. Na prístup k pôvodnej, nechránenej hodnote — napríklad pri ukladaní HTML — použite DotApp::DotApp()->unprotect($variable). Metóda prijíma reťazec alebo pole referenciou a ochranu odstráni rekurzívne. Napríklad:
use \Dotsystems\App\DotApp;
$variable = $_POST['variable'];
DotApp::DotApp()->unprotect($variable); // $variable now contains the original, unprotected value
Všimnite si, že unprotect mení premennú referenciou, preto ho volajte ako DotApp::DotApp()->unprotect($variable) bez priraďovania výsledku (t. j. vyhnite sa $variable = DotApp::DotApp()->unprotect($variable)). Tento prístup posilňuje filozofiu DotApp: vývojári nemusia premenné chrániť ručne, predvolene sú bezpečné, no majú možnosť získať nechránené hodnoty, keď to výslovne potrebujú.
Prístup k inštancii DotApp
Jadro DotApp je dostupné ako DotApp::DotApp(). Použite ho na unprotect, ajaxReply a call. Routovanie, dopyty, view, konfigurácia a session používajú fasády.
use Dotsystems\App\DotApp;
DotApp::DotApp()->unprotect($htmlFromEditor);
DotApp::DotApp()->ajaxReply(['status' => 1], 200);
DotApp::call('HelloWorld:Home@index!', $request);
V initialize($dotApp) je jadro argumentom metódy. Služby registrujte pomocou $dotApp->bind / singleton / resolve. Kontroléry používajú DotApp::DotApp() alebo fasády.
Použitie fasád
Fasády sú verejné API pre základné služby.
Napríklad:
Renderer::new()->module(self::moduleName())->setView("dotapper-cli.eng")->setViewVar("variables", $viewVars)->renderView();
Fasáda Renderer drží kód stručný. Vlastné renderery:
Renderer::add("Docs.code.replace", function($code) { /* logic */ });
Bežné fasády
Renderer::new(): Vráti resetovateľný objekt renderera.Renderer::add(): Pridá vlastný renderer.Router::get(): Definuje GET trasu, napríkladRouter::get(['/helloworld', '/helloworld/'], "HelloWorld:Home@index!", Router::STATIC_ROUTE);.
Používanie fasád zlepšuje čitateľnosť kódu a je v súlade s filozofiou DotApp: čistý, udržiavateľný kód.
Dependency Injection
Vlastné služby registrujte v initialize($dotApp):
public function initialize($dotApp) {
$dotApp->singleton('cache', function () {
return new CacheService();
});
}
Kontroléry vykresľujú pomocou Renderer::new():
public static function index($request) {
return Renderer::new()->module('HelloWorld')->setView('hello')->renderView();
}
Databázové postupy
Aby boli vaše moduly prenosné a nezávislé od ovládača, filozofia DotApp vyžaduje prístup k databáze cez fasádu DB::module(). Táto fasáda podľa konfiguračných nastavení automaticky vyberie nakonfigurovaný ovládač a databázu, čím zabezpečí konzistenciu v celej aplikácii.
Použitie DB::module()
Na databázové dopyty použite DB::module("ORM") alebo DB::module("RAW"):
DB::module("RAW")->q(function ($qb) use ($token) {
$qb
->select('user_id', Config::get("db","prefix").'users_rmtokens')
->where('token', '=', $token);
})->execute(
function ($result) {
// $result is an array of rows in RAW mode
},
function ($error) {
\Dotsystems\App\Parts\Logger::use()->error('query failed', ['msg' => is_object($error) ? $error->getMessage() : (string) $error]);
}
);
Použitie callbackov
Do execute() vždy odovzdajte callback úspechu aj callback chyby. Callback úspechu v režime RAW dostane pole riadkov.
- Callback úspechu:
function($result, $db, $debug)—$resultje v režime RAW pole riadkov. - Callback chyby:
function($error, $db, $debug)— povinný, aby sa zlyhania spracovali.
DB::module("RAW")->q(function ($qb) use ($token) {
$qb
->select('user_id', Config::get("db","prefix").'users_rmtokens')
->where('token', '=', $token);
})->execute(
function ($result, $db, $debug) use (&$data) {
if ($result === null || $result === []) {
$data = [];
setcookie('dotapp_'.Config::get("app","name_hash"), "", [
'expires' => time() - 3600,
'path' => Config::session("path"),
]);
} else {
$db->q(function ($qb) use (&$data, $result) {
$qb
->select(['username', 'password'], Config::get("db","prefix").'users')
->where('id', '=', $result['user_id']);
})->execute(function ($result, $db, $debug) use (&$data) {
$data['username'] = $result[0]['username'];
$data['passwordHash'] = $result[0]['password'];
$data['stage'] = 0;
\Dotsystems\App\Parts\Auth::login($data, true);
}, function ($error, $db, $debug) {
// Handle error, e.g., log or display error message
$data['error'] = $error->getMessage();
});
}
},
function ($error, $db, $debug) {
// Handle initial query error
error_log("Database error: " . $error->getMessage());
}
);
V tomto príklade:
- Callback
successspracuje pole$result, ktoré je nezávislé od ovládača (napríklad$result[0]['user_id']). - Vnorený dopyt používa ďalšie
executes vlastnými callbackmisuccessaerrorna spracovanie výsledkov alebo chýb. - Callback
errorzaloguje alebo spracuje databázové chyby a zabráni nespracovaným výnimkám.
Ak callbacky vedú k zložitému kódu (callback hell), výsledky môžete uložiť do premennej a logiku zjednodušiť:
$dbreturn = null;
DB::module("RAW")->q(function ($qb) use ($token) {
$qb
->select('user_id', Config::get("db","prefix").'users_rmtokens')
->where('token', '=', $token);
})->execute(
function ($result, $db, $debug) use (&$dbreturn) {
$dbreturn = $result;
},
function ($error, $db, $debug) {
error_log("Database error: " . $error->getMessage());
}
);
// Continue logic with $dbreturn
Dôležité: Nevracajte surové objekty ovládača (napríklad $returnDB = DB::module("RAW")->q(...)->execute()), pretože sú špecifické pre ovládač (MySQLi alebo PDO). Používanie callbackov zabezpečí, že modul bude fungovať s ľubovoľným ovládačom, v súlade s filozofiou DotApp.
Správa session pomocou DSM
DotApp Session Manager (DSM) je povinná súčasť správy session a nahrádza priame použitie $_SESSION. DSM abstrahuje podkladový ovládač session (napríklad predvolený, súborový, databázový, Redis), takže vaša aplikácia alebo modul ostane prenosný medzi rôznymi prostrediami.
Použitie DSM
DSM importujte a použite takto:
use \Dotsystems\App\Parts\DSM;
$dsm = new DSM("MyModuleStorage");
$dsm->load();
$dsm->set('variable1', "hello");
Prípadne použite fasádu DSM pre čistejší kód (odporúčané):
DSM::use("MyModuleStorage")->set('variable1', "hello");
echo DSM::use("MyModuleStorage")->get('variable1'); // Outputs: hello
Každý modul by si mal vytvoriť vlastné úložisko (napríklad MyModuleStorage), aby sa vyhol konfliktom s inými modulmi. Premenné v rôznych úložiskách môžu zdieľať rovnaký názov bez kolízií.
Kľúčové metódy DSM
set($name, $value): Nastaví session premennú.get($name): Získa session premennú.delete($name): Odstráni session premennú.clear(): Vymaže všetky premenné v úložisku.start(): Automaticky sa volá v konštruktore.destroy(): Zničí úložisko (voliteľné).session_id(): Vráti ID session.load(): Načíta session (pri fasáde nie je potrebné).save(): Uloží session (automaticky pri zničení).
Najčastejšie používané metódy sú:
DSM::use("MyModuleStorage")->set('variable1', "hello");
DSM::use("MyModuleStorage")->get('variable1');
DSM::use("MyModuleStorage")->delete('variable1');
DSM::use("MyModuleStorage")->clear();
Prečo DSM? Použitie DSM namiesto $_SESSION zabezpečí, že je modul nezávislý od ovládača session. Prístup cez fasádu odstraňuje potrebu ručných volaní load() a robí kód čistejším a udržiavateľnejším.
Pozrieť príklady
Praktické príklady týchto odporúčaných postupov vrátane databázových dopytov s DB::module() a správy session pomocou DSM nájdete v sekcii Príklady. Tieto príklady ukazujú, ako postupy uplatniť v reálnych situáciách.