Εν συντομία: Η PHP έχει δυναμικούς τύπους: ο τύπος μιας τιμής καθορίζεται μόνο κατά την εκτέλεση και, χωρίς περαιτέρω οδηγίες, η PHP μετατρέπει αυτόματα τις τιμές όταν χρειάζεται. Από την PHP 7 όμως μπορείτε να προσθέσετε τύπους σε παραμέτρους, τιμές επιστροφής και ιδιότητες, ενώ το declare(strict_types=1) κάνει τον έλεγχο αυστηρό. Όποιος γνωρίζει τους κανόνες και χρησιμοποιεί αυστηρές συγκρίσεις με === αποφεύγει μια ολόκληρη κατηγορία λογικών σφαλμάτων και σφαλμάτων ασφαλείας.
Δυναμικοί τύποι, αλλά όχι χωρίς τύπους
Στην PHP, στο $preis = 19.90; δεν χρειάζεται να δηλώσετε τύπο. Η PHP αναγνωρίζει ότι πρόκειται για αριθμό κινητής υποδιαστολής. Αν η τιμή συνδυαστεί αργότερα με μια συμβολοσειρά, η PHP τη μετατρέπει. Αυτή η συμπεριφορά ονομάζεται type juggling, δηλαδή αυτόματη μετατροπή τύπων. Κάνει εύκολη την έναρξη, μπορεί όμως να οδηγήσει σε εκπληκτικά αποτελέσματα.
Για όσους αποφασίζουν αυτό έχει σημασία, επειδή πολλές παλαιότερες εφαρμογές PHP γράφτηκαν χωρίς δηλώσεις τύπων. Ένας τέτοιος κώδικας είναι δυσκολότερο να ελεγχθεί και να εκσυγχρονιστεί. Τα νεότερα έργα χρησιμοποιούν τους τύπους με συνέπεια, κάτι που κάνει τα σφάλματα ορατά νωρίτερα και επιτρέπει στη στατική ανάλυση με εργαλεία όπως το PHPStan ή το Psalm να αποδώσει πραγματικά.
Οι τύποι της PHP με μια ματιά
Το εγχειρίδιο της PHP αναφέρει εννέα εσωτερικούς τύπους που μπορεί να έχει κάθε έκφραση. Συνήθως χωρίζονται σε τρεις ομάδες:
| Ομάδα | Τύποι | Παράδειγμα |
|---|---|---|
| Βαθμωτοί τύποι | bool, int, float, string |
true, 42, 3.5, "Text" |
| Σύνθετοι τύποι | array, object, callable |
[1, 2], new DateTime() |
| Ειδικοί τύποι | null, resource |
null, ένα ανοιχτό αρχείο |
Για ελέγχους τύπων το εγχειρίδιο συνιστά τις συναρτήσεις is_*(), όπως η is_int(). Για την εξέταση ενδείκνυται η get_debug_type(), που από την PHP 8.0.0 επιστρέφει τα συνηθισμένα ονόματα τύπων, ενώ η παλαιότερη gettype() επιστρέφει, για παράδειγμα, "integer" και "double".
Εκτός από την αυτόματη μετατροπή υπάρχει και η ρητή: με ένα cast όπως το (int) $wert ή με την settype(), ο ίδιος ο κώδικας καθορίζει ποιον τύπο πρέπει να έχει μια τιμή. Αυτό είναι συνηθισμένο στις εισόδους από φόρμες, επειδή ό,τι έρχεται μέσω των $_GET ή $_POST είναι αρχικά συμβολοσειρά ή πίνακας. Ένα cast δεν ελέγχει όμως αν η τιμή ήταν λογική: το "abc" γίνεται σιωπηλά 0. Για εισόδους, ένας πραγματικός έλεγχος με την filter_var() είναι συνήθως η καλύτερη επιλογή.
Οι κλάσεις και οι διεπαφές (interfaces) είναι επίσης τύποι στην PHP. Μια συνάρτηση μπορεί επομένως να απαιτεί μια παράμετρο να είναι αντικείμενο μιας συγκεκριμένης κλάσης ή να υλοποιεί μια συγκεκριμένη διεπαφή. Πώς συνεργάζονται κλάσεις, διεπαφές και enums, εξηγεί η σελίδα Αντικειμενοστρέφεια στην PHP.
Δηλώσεις τύπων: από την PHP 7.1 ως την 8.3
Οι δηλώσεις τύπων καθορίζουν ποιες τιμές δέχεται και επιστρέφει μια συνάρτηση. Το σύστημα τύπων έχει εξελιχθεί σε πολλές εκδόσεις. Σύμφωνα με το ιστορικό αλλαγών του εγχειριδίου, προστέθηκαν μεταξύ άλλων οι εξής δυνατότητες:
| Έκδοση | Νέο |
|---|---|
| 7.1.0 | τύποι που δέχονται null (?int), void, iterable |
| 7.2.0 | object |
| 7.4.0 | τυποποιημένες ιδιότητες κλάσεων |
| 8.0.0 | τύποι ένωσης (union, πολλοί επιτρεπτοί τύποι σε μία δήλωση), mixed, τύπος επιστροφής static |
| 8.1.0 | τύποι τομής (intersection, A&B), τύπος επιστροφής never |
| 8.2.0 | τύποι DNF, τύπος κυριολεκτικού true, null και false ως αυτόνομοι τύποι |
| 8.3.0 | τυποποιημένες σταθερές κλάσεων, διεπαφών, traits και enums |
Το DNF σημαίνει διαζευκτική κανονική μορφή και επιτρέπει συνδυασμούς όπως (A&B)|null. Όποιος σχεδιάζει εκδόσεις PHP βλέπει από αυτόν τον πίνακα και ποια γλωσσικά μέσα προϋποθέτει μια εφαρμογή.
strict_types: μετατροπή ή TypeError
Χωρίς περαιτέρω δήλωση, η PHP λειτουργεί σε τρόπο λειτουργίας με μετατροπή. Μια συνάρτηση με παραμέτρους int δέχεται τότε και το 1.5 και το κάνει 1· από την PHP 8.1 αυτή η μετατροπή με απώλεια έχει χαρακτηριστεί ως παρωχημένη. Με το declare(strict_types=1) στην αρχή του αρχείου, η PHP πετά αντίθετα ένα TypeError.
<?php
declare(strict_types=1);
function summe(int $a, int $b): int
{
return $a + $b;
}
echo summe(1, 2); // 3
echo summe(1.5, 2.5); // TypeError, αντί για σιωπηλό 3
Δύο λεπτομέρειες είναι σημαντικές. Πρώτον, το strict_types ισχύει για τις κλήσεις από το αρχείο στο οποίο βρίσκεται, όχι για τις συναρτήσεις που ορίζονται εκεί. Αν ένα αρχείο χωρίς strict_types καλέσει την ίδια συνάρτηση, γίνεται μετατροπή. Δεύτερον, ένας ακέραιος εκεί όπου αναμένεται αριθμός κινητής υποδιαστολής επιτρέπεται και στον αυστηρό τρόπο λειτουργίας.
Χαλαρές και αυστηρές συγκρίσεις
Ο τελεστής == συγκρίνει μετά από μετατροπή τύπου, ο === συγκρίνει τιμή και τύπο χωρίς μετατροπή. Το εγχειρίδιο συνιστά στις περισσότερες περιπτώσεις τους === και !==, επειδή οι κανόνες μετατροπής δεν είναι πάντα προφανείς.
<?php
var_dump(0 == "a"); // PHP 7: true, PHP 8: false
var_dump("1" == "01"); // true, και οι δύο είναι αριθμητικές συμβολοσειρές
var_dump("1" === "01");// false, ίδιος τύπος, αλλά διαφορετική συμβολοσειρά
var_dump(1 == true); // true
var_dump(1 === true); // false
Με την PHP 8.0 οι συγκρίσεις μεταξύ αριθμών και μη αριθμητικών συμβολοσειρών έγιναν πιο λογικές. Παλαιότερες εφαρμογές μπορεί να συμπεριφέρονται διαφορετικά μετά την αναβάθμιση, για παράδειγμα σε μπλοκ switch. Η έκφραση match, που εισήχθη επίσης με την PHP 8.0, συγκρίνει πάντα αυστηρά. Πώς οι χαλαρές συγκρίσεις οδηγούν σε ευπάθειες, για παράδειγμα σε ελέγχους tokens ή κωδικών πρόσβασης, περιγράφει το άρθρο Type juggling: οι χαλαρές συγκρίσεις ως κίνδυνος ασφαλείας.
Τύποι, αναβαθμίσεις και PHP2Shell
Ένα αυστηρό σύστημα τύπων κάνει τον κώδικα της εφαρμογής πιο στιβαρό, αλλά δεν προστατεύει από σφάλματα στον ίδιο τον διερμηνέα. Οι ευπάθειες PHP2Shell CVE-2026-109618 και CVE-2026-109619 βρίσκονται στη διαχείριση μνήμης και αιτημάτων της PHP. Έχουν διορθωθεί στις PHP 8.5.12, 8.4.27, 8.3.36 και 8.2.35· μετά από αυτό πρέπει να γίνει επανεκκίνηση όλων των διεργασιών PHP.
Το σύστημα τύπων παίζει παρ' όλα αυτά ρόλο, και συγκεκριμένα στην αναβάθμιση. Οι εφαρμογές που παραμένουν ακόμη στην PHP 8.1 ή παλαιότερη δεν λαμβάνουν πλέον επίσημες ενημερώσεις από το έργο PHP. Ένας κώδικας με καλούς τύπους μεταφέρεται πολύ ευκολότερα σε υποστηριζόμενη έκδοση, επειδή τα εργαλεία εντοπίζουν νωρίς τις ασυμβατότητες. Στα παλαιότερα έργα βοηθά η μετάβασή μας σε υποστηριζόμενη έκδοση PHP.
Ενεργοποιήστε το strict_types σταδιακά σε νέα και αναθεωρημένα αρχεία. Έτσι αυξάνεται η ασφάλεια τύπων χωρίς να χαλάσει ξαφνικά ο παλιός κώδικας.
Πώς βοηθά συγκεκριμένα η PHP SOS;
- Ελέγχουμε ποια έκδοση PHP χρειάζεται τουλάχιστον η εφαρμογή σας και την αντιπαραβάλλουμε με τις διορθωμένες εκδόσεις.
- Εκτελούμε στατική ανάλυση στον κώδικα και επισημαίνουμε σημεία με χαλαρές συγκρίσεις σε ελέγχους σχετικούς με την ασφάλεια.
- Σχεδιάζουμε τις αναβαθμίσεις έτσι ώστε οι αλλαγμένοι κανόνες σύγκρισης να δοκιμάζονται εκ των προτέρων.
- Εγκαθιστούμε την ενημέρωση της PHP, επανεκκινούμε όλους τους workers και τεκμηριώνουμε την κατάσταση.
Συχνές ερωτήσεις
Είναι η PHP γλώσσα με ισχυρούς ή με ασθενείς τύπους;
Η PHP έχει δυναμικούς τύπους: ο τύπος μιας μεταβλητής καθορίζεται μόνο κατά την εκτέλεση. Χωρίς strict_types η PHP μετατρέπει τιμές όταν χρειάζεται. Με δηλώσεις τύπων και strict_types, ο κώδικας μπορεί ωστόσο να γίνει πολύ αυστηρός.
Τι επιτυγχάνει το declare(strict_types=1);
Απενεργοποιεί την αυτόματη μετατροπή βαθμωτών τιμών για τις κλήσεις από το συγκεκριμένο αρχείο. Αν μια τιμή δεν ταιριάζει με τον δηλωμένο τύπο, η PHP πετά ένα TypeError. Μοναδική εξαίρεση είναι ένας ακέραιος εκεί όπου αναμένεται αριθμός κινητής υποδιαστολής.
Γιατί το 0 == «a» είναι ψευδές στην PHP 8, ενώ στην PHP 7 ήταν αληθές;
Έως την PHP 7, μια μη αριθμητική συμβολοσειρά μετατρεπόταν σε αριθμό κατά τη σύγκριση με έναν αριθμό, και το «a» γινόταν 0. Από την PHP 8.0 η PHP δεν συγκρίνει πλέον αριθμητικά σε αυτή την περίπτωση, και το αποτέλεσμα είναι false.
Προστατεύουν οι τύποι από ευπάθειες της ίδιας της PHP;
Όχι. Οι τύποι αποτρέπουν σφάλματα στον κώδικα της εφαρμογής σας. Οι ευπάθειες στον διερμηνέα, όπως το PHP2Shell, κλείνουν μόνο με ενημέρωση της PHP. Τα σύγχρονα χαρακτηριστικά τύπων προϋποθέτουν όμως πρόσφατες εκδόσεις της PHP και αποτελούν έτσι καλή αφορμή για αναβάθμιση.