Poczytałem trochę o MVC, przeanalizowałem kody, nawet wyklepałem swój własny. Wszystko działa, tylko że przy wpisaniu niedozwolonych znaków nie wyświetla błędu, lecz przekierowuje na stronę startową. Kod jest na podstawie tego z PHP Zaawansowane Programowanie, klasa request jest taka sama.
Sam nie lubię jak ktoś na forum wkleja ogromne kody, ale ufam, że większość ludzi zna chociażby klasę request właśnie z tej książki ;) Na wszelki wypadek ją wkleję:
(może od razu powiem, że kod tylko zwiększa o 1 liczbę wpisywaną do pola tekstowego [rotfl] )
klasa request:
<?php
require_once('constants.phpm');
require_once('constraint.phpm');
require_once('constraintfailure.phpm');
class Request {
private $GetVars; // tablice GET
private $PostVars; // tablice POST
private $CookieVars; // tablice COOKIES
private $RequestVars; // tablice REQUEST
private $OriginalRequestObject; // kopia parametrów REQUEST w przypadku, gdy nastąpiło przekierowanie na pierwotną strnę
private $RedirectFollowingFailure; // okresla, czy obiekt OriginalRequest zostal utworzony przez przekierowanie na strone pierwotną
private $RedirectOnFailure; // okresla, czy w przypadku nieprawidlowosci przekierowanie nastapilo na pierwotną stronę czy na inny adres URL
private $FailureRedirectURL; // gdy powyższa zmienna ma wartosc true, zwraca adres przekierowania
private $FailureDefaultRedirectURL; // gry powyzsza zmienna ma pusta wartosc, a OnFC ma wartość TRUE
private $ParameterMethodHash; // tablica ograniczeń, zawiera nazwę parametru, sposób, w jaki parametr ma zostać przesłany oraz obiekt
// ograniczenia reprezentujący test, jak ma zostać wykonany
private $HasRunTests; // czy na danym obiekcie przeprowadzono już testy prawidłowości
private $Failures; // tablica obiektów reprezentujących tetsty, które wypadły negatywnie
function __construct($check_for_cookie = true) {
global $_GET;
global $_POST;
global $_COOKIE;
global $_REQUEST;
$this->GetVars = $_GET;
$this->PostVars = $_POST;
$this->CookieVars = $_COOKIE;
$this->RequestVars = $_REQUEST;
if ($check_for_cookie) {
if ($this->CookieVars["phprqcOriginalRequestObject"]) {
$cookieVal = $this->RequestVars["phprqcOriginalRequestObject"];
$this->RedirectFollowingFailure = true;
if (strlen($cookieVal) > 0) {
$strResult = setcookie("phprqcOriginalRequestObject", "", time() - 3600, "/");
$origObj = unserialize(stripslashes($cookieVal));
$this->OriginalRequestObject = &$origObj;
$this->RequestVars["phprqcOriginalRequestObject"] = "";
$this->GetVars["phprqcOriginalRequestObject"] = "";
$this->PostVars["phprqcOriginalRequestObject"] = "";
}
$this->RedirectOnFailure = true;
} else {
$this->RedirectOnFailure = false;
}
} else {
$this->RedirectOnFailure = false;
}
$this->ParameterMethodHash = array(); // rozdzielenie zmiennej na tablicę
$this->Failures = array(); // rozdzielenie zmiennej na tablicę
$this->HasRunTests = false; // nie zaczęto testó tworząc obiekt klasy request
}
function IsRedirectFollowingFailure() {
return($this->RedirectOnFailure); // zwraca informacje, czy ma zostac wywolane automatyczne przekierowanie na inny adres URL
}
function GetOriginalRequestObject() {
if($this->RedirectOnFailure) {
return($this->OriginalRequestObject); // zwraca oryginalne zmienne $_REQUEST jeśli nastąpiło przekierowanie na pierwotną stronę
}
}
function SetRedirectOnFailure($TrueOrFalse) {
$this->RedirectOnFailure = $TrueOrFalse; // okresla, czy ma zostac wywolane automatyczne przekierowanie na inny adres URL, czy na stronę pierwotną
}
function SetRedirectTargetURL($URL) {
$this->FailureRedirectURL = $URL; // ustala adres przekierowania
}
function SetDefaultRedirectURL($URL) {
$this->FailureDefaultRedirectURL = $URL; // ustala adres przekierowania, jesli poprzednia funkcja jest pusta
}
function GetParameterValue($Parameter) {
return($this->RequestVars[$Parameter]); // zwraca określoną wartosc $_REQUEST
}
function GetParameter() {
return($this->RequestVars); // zwraca bezposrednia kopie $_REQUEST
}
function AddConstraint($Parameter, $Method, $Constraint) {
$newHash["PARAMETER"] = $Parameter;
$newHash["METHOD"] = $Method;
$newHash["CONSTRAINT"] = $Constraint;
$this->ParameterMethodHash[] = $newHash; // nadaje ograniczenia
}
function TestConstraints() {
$this->HasRunTests = true;
$anyFail = false;
for ($i = 0; $i <= sizeof($this->ParameterMethodHash)-1; $i++) {
$Parameter = $this->ParameterMethodHash[$i]["PARAMETER"];
$Method = $this->ParameterMethodHash[$i]["METHOD"];
$Constraint = $this->ParameterMethodHash[$i]["CONSTRAINT"];
$ActualValue = "";
if($Method == VERB_METHOD_GET) {
$ActualValue = $this->GetVars[$Parameter];
}
if($Method == VERB_METHOD_POST) {
$ActualValue = $this->PostVars[$Parameter];
}
$ConstraintType = $Constraint->GetConstraintType();
$ConstraintOperand = $Constraint->GetConstraintOperand();
$Fail = false;
$FailureObject = new ConstraintFailure($Parameter, $Method, $Constraint);
switch ($ConstraintType) {
case CT_MINLENGTH:
if(strlen((string)$ActualValue) < (integer)$ConstraintOperand) {
$Fail = true;
}
break;
case CT_MAXLENGTH:
if(strlen((string)$ActualValue) > (integer)$ConstraintOperand) {
$Fail = true;
}
break;
case CT_PERMITTED_CHARACTERS:
for ($j = 0; $j <= strlen($ActualValue)-1; $j++) {
$Char = substr($ActualValue, $j, 1);
if (!(strpos($ConstraintOperand, $Char) === false)) {
$Fail = true;
}
}
break;
case CT_NON_PERMITTED_CHARACTERS:
for ($j = 0; $j <= strlen($ActualValue)-1; $j++) {
$Char = substr($ActualValue, $j, 1);
if (strpos($ConstraintOperand, $Char) === false) {
$Fail = true;
}
}
break;
case CT_LESSTHAN:
if($ActualValue >= $ConstraintOperand) {
$Fail = true;
}
break;
case CT_MORETHAN:
if($ActualValue <= $ConstraintOperand) {
$Fail = true;
}
break;
case CT_EQUALTO:
if($ActualValue != $ConstraintOperand) {
$Fail = true;
}
break;
case CT_NOT_EQUALTO:
if($ActualValue == $ConstraintOperand) {
$Fail = true;
}
break;
case CT_MUST_MATCH_REGEXP:
if(!(preg_match($ConstraintOperand, $ActualValue))) {
$Fail = true;
}
break;
case CT_MUST_NOT_MATCH_REGEXP:
if(preg_match($ConstraintOperand, $ActualValue)) {
$Fail = true;
}
break;
}
if($Fail) {
$anyFail = true;
$this->ConstraintFailure[] = $FailureObject;
}
}
if($anyFail) {
if($this->RedirectOnFailure) {
$targetURL = $_ENV["HTTP_REFERER"];
if(!$targetURL) {
$targetURL = $this->FailureDefaultRedirectURL;
}
if($this->FailureRedirectURL) {
$targetURL = $this->FailureRedirectURL;
}
if($targetURL) {
$objToSerialize = $this;
$strSerialization = serialize($objToSerialize);
header("Location: $targetURL");
exit(0);
}
}
}
return(!($anyFail)); // zwraca TRUE, jesli wszystkie testy wypadly pomyslnie, w przeciwnym wypadku zwraca FALSE
}
function GetConstraintFailures() {
if(!$this->HasRunTests) {
$this->TestConstraints();
}
return($this->ObjConstraintFailure);
}
}
?>
I teraz kod aplikacji. Wszystko zaczyna się od tego pliku:
<?php
// model, wywoływany jako pierwszy
require_once('constants.phpm');
require_once('constraint.phpm');
require_once('constraintfailure.phpm');
require_once('controller.php');
$templateFile = 'inkrementajka.phtml'; // zdefiniowanie pliku szablonu
$displayHash = array(); // inicjalizacja zmiennej przechowującej ewentualne błędy
$objRequest = new Request();
$hadProblems = $objRequest->IsRedirectFollowingFailure();
$displayHash["HADPROBLEMS"] = $hadProblems;
if ($hadProblems) { // jeśli pojawiły się błędy
$failingRequest = $objRequest->GetOriginalRequestObject();
$failures = $objRequest->GetConstraintFailures();
$displayHash["PROBLEMS"] = array();
for ($i = 0; $i < sizeof($failures); $i++) {
$thisFailure = &$failures[$i];
$thisFailing = $thisFailure->GetFailedObject();
$typeOfFailure = $thisFailing->GetConstraintType();
switch ($typeOfFailure) {
case CT_PERMITTED_CHARACTERS:
$displayHash["PROBLEMS"][] = "Wpisane dane nie są liczbą";
break;
}
}
}
require_once($templateFile);
exit(0);
?>
inkrementajka.phtml, czyli plik dołączany w poprzednim kodzie:
<html>
<head>
<title>Inkrementajka Jebajka</title>
</head>
<body>
<-- widok, wywoływany jako pierwszy -->
<h1>Inkrementajka Jebajka</h1>
<form method="get" action="inkrementajkaResults.php">
<input type="text" name="liczba" /><br />
<input type="submit" value="Jebaj!" />
</form>
<?php if($displayHash["PROBLEMS"]) { ?>
Niestety, wystąpiły problemy.<br />
<?php for ($i = 0; $i < sizeof($displayHash["PROBLEMS"]); $i++) { echo $displayHash["PROBLEMS"][$i]; } } ?>
</body>
</html>
inkrementajkaResults.php, plik do którego następuje przekierowanie po wpisaniu liczby w polu tekstowym w poprzednim pliku:
<?php
// kontroler, wywoływany jako drugi, po wpisaniu liczby w polu tekstowym
require_once('constants.phpm');
require_once('constraint.phpm');
require_once('constraintfailure.phpm');
require_once('controller.php');
$templateFile = "inkrementajkaResults.phtml";
$displayHash = array();
$objRequest = new Request();
$objRequest->SetRedirectOnFailure(true);
$objConstraint = new Constraint(CT_NON_PERMITTED_CHARACTERS, "1234567890");
$objRequest->AddConstraint("liczba", VERB_METHOD_GET, $objConstraint);
$objRequest->SetDefaultRedirectURL("inkrementajka.php");
$objRequest->TestConstraints();
// w tym miejscu wszystkie testy zakończyły się powodzeniem, można więc rozpocząć inkrementację
$displayHash["RESULT"] = $objRequest->GetParameterValue("liczba") + 1;
require_once($templateFile);
exit(0);
?>
Plik dołączany w poprzednim kodzie:
<html>
<head>
<title>Inkrementajka Jebajka</title>
</head>
<body>
<-- widok drugi z wynikami, wywoływany jako czwarty i ostatni -->
<h1>Inkrementajka Jebajka</h1>
<h3>Wyniki inkrementajki jebajki:</h3>
<?php echo $displayHash["RESULT"]; ?>
<br /><br />
<a href="inkrementajka.php">Wróć, aby zinkrementować inną liczbę</a>
</body>
</html>
Może jestem ślepy, ale nie wiem, co jest nie tak. Podejrzewam, że to dlatego, ponieważ nic się nie zapisuje do zmiennej RedirectOnFailure w klasie Request, nie wiem czemu.
Z góry dzięki za pomoc i cierpliwość, jeśli chociażby komuś chciało się przewinąć na dół nie załamując rąk, patrząc na taki kod wklejony na forum ;)