php — συγκεντρωτικός οδηγός — DedSec Project
php — συγκεντρωτικός οδηγός PHP Περιβάλλον εκτέλεσης Η PHP λειτουργεί σε CLI ή μέσω web server. Η επιτυχία στη γραμμή εντολών δεν αποδεικνύει ότι είναι σωστές οι HTTP κεφαλίδες ή η…
PHP
Περιβάλλον εκτέλεσης
Η PHP λειτουργεί σε CLI ή μέσω web server. Η επιτυχία στη γραμμή εντολών δεν αποδεικνύει ότι είναι σωστές οι HTTP κεφαλίδες ή η επεξεργασία παραμέτρων. Κατέγραψε την έκδοση και το περιβάλλον εκτέλεσης πριν συγκρίνεις αποτελέσματα.
Εργαστήριο: απουσία, λανθασμένος τύπος και HTML
Αποθήκευσε ως safe-label.php. Εκτέλεσε php -l safe-label.php && php safe-label.php με PHP 8+.
<?php
declare(strict_types=1);
function safe_label(array $query): string {
if (!array_key_exists('label', $query)) return '(missing)';
if (!is_string($query['label'])) return '(invalid)';
return htmlspecialchars(trim($query['label']), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
$tests = [
[['label' => ' Ada & Co '], 'Ada & Co'],
[[], '(missing)'],
[['label' => ['unexpected']], '(invalid)'],
[['label' => '<script>'], '<script>'],
];
foreach ($tests as [$input, $expected]) {
if (safe_label($input) !== $expected) throw new RuntimeException('failed');
}
echo count($tests), " checks passed\n";
Αναμενόμενη έξοδος: 4 checks passed. Ένα ανύπαρκτο κλειδί διαφέρει από ένα κλειδί που περιέχει πίνακα. Η κωδικοποίηση HTML εφαρμόζεται στο σημείο εμφάνισης· δεν καθιστά ασφαλές ένα SQL ερώτημα. Για SQL χρησιμοποίησε δεσμευμένες παραμέτρους, ενώ για JSON κατάλληλη κωδικοποίηση JSON.
Διάγνωση ανά σύμπτωμα
- Undefined array key: έλεγξε πρώτα αν υπάρχει το κλειδί. Η
array_key_existsξεχωρίζει την απουσία από τοnull, ενώ το??συνήθως τα συνδυάζει. - TypeError: μια παράμετρος όπως
?label[]=xμπορεί να φτάσει ως πίνακας. Έλεγξε τον τύπο πριν από συναρτήσεις συμβολοσειρών. - Headers already sent: εντόπισε πρόωρη έξοδο ή BOM πριν από
header()καιsetcookie(). Μην κρύβεις την προειδοποίηση. - Λειτουργεί στο CLI αλλά όχι στον ιστό: σύγκρινε εκδόσεις PHP, επεκτάσεις, ρυθμίσεις ini, δρομολόγηση, δικαιώματα και logs. Το
php --iniαφορά το CLI και όχι κατ' ανάγκη τον web runtime. - Λάθος χαρακτήρες: έλεγξε τη χρήση UTF-8 σε HTTP και HTML.
Διαδρομή κατάκτησης
- Πρόβλεψε τις τέσσερις εξόδους, εκτέλεσε το αρχείο και σημείωσε έκδοση PHP και αποτέλεσμα.
- Πρόσθεσε
['label' => ' "quoted" ']και έλεγξε ότι επιστρέφει"quoted". Εξήγησε τοENT_QUOTES. - Σε τοπικό δοκιμαστικό server, κάλεσε
safe_label($_GET)και δοκίμασε απουσία παραμέτρου και?label[]=x. - Αφαίρεσε προσωρινά τον έλεγχο τύπου, κατέγραψε την αποτυχία, επανέφερέ τον και εξήγησε την αιτία.
Επίσημη πηγή: https://www.php.net/manual/en/function.htmlspecialchars.php
PHP — Αναλυτικός οδηγός εξάσκησης
Γιατί χρειάζεται σύμβαση
Οι δυαδικοί δεκαδικοί κινητής υποδιαστολής μπορούν να δώσουν απροσδόκητη στρογγυλοποίηση. Αποθήκευσε ποσότητες και τιμές σε ακέραιες μικρότερες μονάδες όπου το επιτρέπει το πρόβλημα και έλεγξε κάθε εγγραφή από JSON.
Εκτέλεση
Αποθήκευσε total.php και τρέξε php total.php με PHP που υποστηρίζει JSON_THROW_ON_ERROR. Περιμένεις 375 cents. Δεν χρειάζεται web server ή βάση.
<?php
declare(strict_types=1);
function totalCents(array $rows): int {
$total = 0;
foreach ($rows as $row) {
if (!is_array($row) ||
!isset($row["qty"], $row["unit_cents"]) ||
!is_int($row["qty"]) || !is_int($row["unit_cents"])) {
throw new InvalidArgumentException("invalid row");
}
$qty = $row["qty"];
$price = $row["unit_cents"];
if ($qty < 0 || $price < 0 ||
($qty > 0 && $price > intdiv(PHP_INT_MAX - $total, $qty))) {
throw new InvalidArgumentException("invalid amount or overflow");
}
$total += $qty * $price;
}
return $total;
}
$rows = json_decode('[{"qty":2,"unit_cents":150},{"qty":1,"unit_cents":75}]',
true, 512, JSON_THROW_ON_ERROR);
if (totalCents($rows) !== 375) throw new RuntimeException("bad total");
echo "375 cents\n";
Ερμηνεία
Η json_decode με true επιστρέφει associative arrays. Οι έλεγχοι τύπων απορρίπτουν κείμενο "2" ακόμη κι αν μοιάζει αριθμός. Αρνητικές ποσότητες και τιμές απορρίπτονται. Ο έλεγχος intdiv πριν τον πολλαπλασιασμό προστατεύει από overflow του PHP_INT_MAX. Βασίζεται στο ότι το ήδη συγκεντρωμένο άθροισμα είναι μη αρνητικό.
Προκλήσεις
Δοκίμασε δεκαδική ποσότητα, τιμή που λείπει, αρνητικό αριθμό, άδειο array, άκυρο JSON και πολύ μεγάλο γινόμενο. Αποφάσισε αν επιτρέπεται μηδενική ποσότητα. Φτιάξε ξεχωριστή συνάρτηση εμφάνισης ποσών· μην αποθηκεύεις διαμορφωμένα strings ως αριθμούς.
Διάγνωση και ασφάλεια
Έλεγξε php -v και php -l total.php. Ένα undefined array key δείχνει ανεπαρκή επικύρωση. Μη βάζεις εξωτερικές τιμές απευθείας σε SQL ή HTML: οι bound parameters και το HTML escaping λύνουν διαφορετικά προβλήματα. Επιτυχία: 375 cents και σωστή απόρριψη λαθών. https://www.php.net/manual/en/function.json-decode.php
PHP — Παραδείγματα πραγματικού κώδικα
Εκτέλεση των υπαρχόντων αρχείων
Στον φάκελο PHP εκτέλεσε php -v, php -l Practical_Code/01_safe_output.php, php Practical_Code/01_safe_output.php και php Practical_Code/02_arrays.php. Το πρώτο αρχείο εμφανίζει το όνομα Ada <script> με κωδικοποίηση HTML. Το δεύτερο φιλτράρει τον πίνακα [3, 7, 9] και εμφανίζει λίστα JSON με 7 και 9. Αρκεί η PHP στο τερματικό· δεν απαιτείται web server ή δίκτυο.
Πείραμα: κωδικοποίηση εξόδου
Το πρώτο αρχείο καλεί htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'). Άλλαξε το δοκιμαστικό όνομα σε Ada & Bob και πρόβλεψε την κωδικοποίηση του &. Δοκίμασε κενή συμβολοσειρά και εισαγωγικά. Η συνάρτηση είναι κατάλληλη για κείμενο HTML, όχι για SQL, πηγαίο κώδικα JavaScript, CSS ή αυθαίρετα URL. Έλεγξε την είσοδο ξεχωριστά και κωδικοποίησε μία φορά στο σημείο εξόδου. Αν εμφανίζονται οι οντότητες κυριολεκτικά, έλεγξε διπλή κωδικοποίηση και τύπο απόκρισης.
Πείραμα: κλειδιά πινάκων και μορφή JSON
Η array_filter διατηρεί τα αρχικά κλειδιά. Με όριο 7 στον πίνακα [3, 7, 9] μένουν οι δείκτες 1 και 2. Η array_values δημιουργεί συνεχόμενους δείκτες, ώστε η json_encode να δώσει λίστα JSON αντί για αντικείμενο. Αφαίρεσε προσωρινά την array_values και σύγκρινε. Δοκίμασε όρια 3, 7 και 10, συμπεριλαμβάνοντας το κενό αποτέλεσμα.
Αναπαραγώγιμος έλεγχος
Αποθήκευσε ως check.php και εκτέλεσε php -l check.php && php check.php:
<?php
declare(strict_types=1);
$encoded = htmlspecialchars('Ada & Bob', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
$numbers = array_values(array_filter([3, 7, 9], fn(int $n): bool => $n >= 7));
if ($encoded !== 'Ada & Bob' || $numbers !== [7, 9]) exit(1);
echo "OK\n";
Μη μηδενικός κωδικός εξόδου σημαίνει αποτυχία. Αν δεν ανοίγει αρχείο, έλεγξε pwd και διαδρομή. Αν το JSON έχει απροσδόκητα κλειδιά, εξέτασε array_keys.
Τεκμήρια ολοκλήρωσης
Κατέγραψε έκδοση PHP, ακριβείς εντολές και έξοδο για κανονικές και οριακές τιμές. Εξήγησε γιατί η κωδικοποίηση HTML και η επαναρίθμηση φιλτραρισμένης λίστας λύνουν διαφορετικά προβλήματα. Επανέφερε τα αρχικά αρχεία μετά το πείραμα.
PHP — Διαδρομή ουσιαστικής εξάσκησης
Επικύρωση στον διακομιστή
Δημιούργησε form.php σε προσωρινό φάκελο. Χρησιμοποίησε μόνο δοκιμαστικά ονόματα. Οι περιορισμοί της φόρμας βοηθούν τον χρήστη, αλλά παρακάμπτονται· η PHP 8.0+ πρέπει να ελέγχει ανεξάρτητα την είσοδο POST.
<?php
declare(strict_types=1);
function validateName(mixed $value): array {
if (!is_string($value)) return [null, 'Name must be text'];
$name = trim($value);
if (!preg_match('/\A[\p{L} ]{1,40}\z/u', $name)) {
return [null, 'Use 1-40 letters or spaces'];
}
return [$name, null];
}
function htmlText(string $s): string {
return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
$post = ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST';
[$name, $error] = $post ? validateName($_POST['name'] ?? null) : [null, null];
?>
<form method="post">
<label for="name">Εμφανιζόμενο όνομα</label>
<input id="name" name="name" required maxlength="40" aria-describedby="hint">
<p id="hint">Μόνο γράμματα και κενά.</p>
<button type="submit">Έλεγχος</button>
</form>
<?php if ($error !== null): ?>
<p role="alert"><?= htmlText($error) ?></p>
<?php elseif ($post): ?>
<p><?= htmlText('Γεια σου, ' . $name) ?></p>
<?php endif; ?>
Η κανονική έκφραση δέχεται γράμματα Unicode και απλά κενά, αλλά αποκλείει παύλες, αποστρόφους και συνδυαστικά διακριτικά. Είναι περιοριστικός κανόνας άσκησης, όχι καθολικός κανόνας για πραγματικά ονόματα.
Εκτέλεση και διερεύνηση
Έλεγξε τη σύνταξη με php -l form.php. Εκτέλεσε php -S 127.0.0.1:8000 στον ίδιο φάκελο και υπέβαλε Ada, Μαρία, κενή τιμή και κείμενο που μοιάζει με HTML. Ο ενσωματωμένος server είναι μόνο για τοπική ανάπτυξη. Ο browser μπορεί να εμποδίσει την κενή τιμή, αλλά η PHP πρέπει να απορρίπτει απευθείας κενό POST. Δοκίμασε name[]=x ώστε ένας πίνακας να μην προκαλεί σφάλμα τύπου. Ξεχώρισε HTTP 404 (λάθος φάκελος), πεδίο που λείπει (λάθος name), άκυρη είσοδο και παράλειψη κωδικοποίησης εξόδου.
Οριακές τιμές και επέκταση
Δοκίμασε 40 και 41 γράμματα. Κατέγραψε κωδικό HTTP και έξοδο χωρίς προσωπικά δεδομένα. Φόρμα που μεταβάλλει δεδομένα χρειάζεται προστασία CSRF και ασφαλείς συνεδρίες· εδώ εμφανίζεται μόνο χαιρετισμός. Ένα API με JSON χρειάζεται ελεγχόμενη απόκριση 4xx και σαφή τύπο περιεχομένου.
Τεκμήρια επάρκειας
Κατέγραψε έκδοση PHP, έλεγχο σύνταξης, κανονικές, άκυρες και οριακές τιμές, καθώς και τι εκτελέστηκε σε browser ή CLI. Εξήγησε γιατί η επικύρωση εισόδου και η κωδικοποίηση HTML προστατεύουν διαφορετικά όρια εμπιστοσύνης.
PHP — Τεχνικά σημεία και συχνές παγίδες
Επικύρωση χωρίς σιωπηρή μετατροπή τύπου
Η PHP μπορεί να μετατρέπει αριθμητικές συμβολοσειρές σε συγκρίσεις και πράξεις. Στο όριο ενός αιτήματος χρειάζεται ρητός κανόνας. Το παράδειγμα δέχεται δεκαδικές συμβολοσειρές από 0 έως 120, απορρίπτει αρχικά μηδενικά, κενά, πρόσημα, πίνακες και τιμές εκτός ορίων και επιστρέφει null σε αποτυχία:
<?php
declare(strict_types=1);
function parseAge(mixed $value): ?int {
if (!is_string($value) ||
!preg_match('/\A(?:0|[1-9][0-9]{0,2})\z/', $value)) return null;
$age = (int) $value;
return $age <= 120 ? $age : null;
}
foreach (['0', '120', '121', '01', '-1'] as $input) {
echo $input . ' => ' . var_export(parseAge($input), true) . "\n";
}
Οι δύο πρώτες τιμές γίνονται δεκτές· οι άλλες τρεις δίνουν NULL. Το εύρος είναι κανόνας άσκησης, όχι καθολικός ορισμός ηλικίας. Ένα πεδίο age[] μπορεί να φτάσει ως πίνακας και απορρίπτεται από τον έλεγχο τύπου.
Διατεταγμένοι χάρτες και JSON
Οι πίνακες PHP είναι διατεταγμένοι χάρτες με ακέραια ή λεκτικά κλειδιά. Η array_filter διατηρεί τα κλειδιά, οπότε φιλτραρισμένος αριθμητικός πίνακας μπορεί να γίνει αντικείμενο JSON. Χρησιμοποίησε array_values όταν απαιτείται λίστα JSON. Έλεγξε απρόσμενη μορφή με array_keys. Η json_decode($text, true, 512, JSON_THROW_ON_ERROR) προκαλεί JsonException σε άκυρο JSON· διαχειρίσου την εξαίρεση χωρίς να θεωρείς την αποτυχία έγκυρη είσοδο.
Κωδικοί πρόσβασης και διαγνωστικά
Αποθήκευσε επαληθευτές με password_hash($password, PASSWORD_DEFAULT) και έλεγξε υποψήφιες τιμές με password_verify. Τα salted hashes διαφέρουν μεταξύ εκτελέσεων· μην συγκρίνεις νέα hashes, μην καταγράφεις μυστικά και μην αντικαθιστάς το password hashing με απλό SHA-256. Η password_needs_rehash βοηθά στην αλλαγή πολιτικής. Η php -l file.php ελέγχει σύνταξη, η php -v έκδοση CLI και η php -m επεκτάσεις. Ο web server μπορεί να έχει άλλες ρυθμίσεις. Μην εμφανίζεις display_errors δημόσια και αφαίρεσε προσωρινές σελίδες phpinfo().
Επαλήθευση
Έλεγξε parseAge('0') === 0, parseAge('121') === null και parseAge('01') === null. Δοκίμασε συνθετικό password με σωστή και λάθος τιμή· δώσε άκυρο JSON και διαχειρίσου JsonException. Κατέγραψε πραγματική έξοδο και εξήγησε γιατί επικύρωση, κωδικοποίηση HTML, παραμετροποιημένη SQL και hashing προστατεύουν διαφορετικά όρια εμπιστοσύνης.