ΚΕΝΤΡΟ ΠΛΗ.ΝΕ.Τ. Ν. ΦΛΩΡΙΝΑΣ

Η Βίβλος της PHP - Μέρος 3γ -
Οι Συναρτήσεις : Διάφορα

 

Έλεγχος Διαθεσιμότητας Συνάρτησης

bool function_exists ( string function_name)

Αν δουλεύουμε με συναρτήσεις που δεν αποτελούν μέρος του πυρήνα της PHP, δηλ. συναρτήσεις που προέρχονται από μια επέκταση (extension) που πρέπει να ενεργοποιηθεί από τους χρήστες, αποτελεί καλή τακτική να χρησιμοποιούμε τη συνάρτηση function_exists(). Η συνάρτηση αυτή δέχεται ένα όνομα συνάρτησης ως τη μοναδική της παράμετρο και επιστρέφει την τιμή true αν η συνάρτηση αυτή είναι διαθέσιμη για χρήση ή την τιμή false αν η συνάρτηση δεν είναι διαθέσιμη για χρήση.

 

Συναρτήσεις Επέκτασης (Extension Functions)

array get_loaded_extensions ( )

array get_extension_funcs ( string module_name)

int dl ( string module_name)

bool extension_loaded ( string name)

Υπάρχουν δύο συναρτήσεις που είναι χρήσιμες για να μπορέσουμε να διαπιστώσουμε ποιες επεκτάσεις (extensions) είναι διαθέσιμες, που είναι η get_loaded_extensions() και η get_extension_funcs(). Επιπλέον, η συνάρτηση dl() φορτώνει δυναμικά (Dynamically Loads) μια επέκταση (extension) της PHP την ώρα της εκτέλεσης (runtime), που σημαίνει ότι μπορούμε να ενεργοποιήσουμε μια συγκεκριμένη επέκταση μόνο για ένα συγκεκριμένο script.

Η συνάρτηση get_loaded_extensions() δεν δέχεται παραμέτρους και επιστρέφει έναν πίνακα (array) με τα ονόματα όλων των επεκτάσεων που έχουμε φορτώσει. Η συνάρτηση get_extension_funcs() δέχεται το όνομα μιας επέκτασης και επιστρέφει έναν πίνακα (array) των συναρτήσεων που είναι διαθέσιμες μέσα σ’ αυτήν την επέκταση.

Χρησιμοποιώντας τις δύο αυτές συναρτήσεις μαζί είναι εύκολο να δοκιμάσουμε αν είναι διαθέσιμη μια επέκταση και αν ναι, ότι περιέχει τη σωστή συνάρτηση. Ας δούμε το επόμενο κομμάτι κώδικα : 

<?php

$extensions = get_loaded_extensions();

foreach($extensions as $extension) {

echo $extension;

                             echo ' (', implode(', ', get_extension_funcs($extension)), ')<br />';

}

?>

Ο παραπάνω κώδικας επιστρέφει τα ονόματα όλων των επεκτάσεων που είναι φορτωμένες και τις εμφανίζει όλες μ’ έναν βρόχο foreach. Για κάθε επέκταση, καλεί τη συνάρτηση get_extension_funcs() για να βρει όλες τις συναρτήσεις που είναι διαθέσιμες μ’ αυτήν την επέκταση και να τις εμφανίσει χωρισμένες με κόμματα και μέσα σε παρενθέσεις.

Για παράδειγμα, αν έχουμε εγκαταστήσει την επέκταση wddx, θα πρέπει να δούμε την παρακάτω γραμμή κάπου ανάμεσα στο αποτέλεσμα :

wddx (wddx_serialize_value, wddx_serialize_vars, wddx_packet_start, wddx_packet_end, wddx_add_vars, wddx_deserialize)

Βλέπουμε ότι ο κώδικας χρησιμοποιεί την εντολή echo και όχι την print επειδή χρησιμοποιεί τον τελεστή του κόμματος (,) για να ενώσει τα μηνύματα για την έξοδο, που είναι πιο αποτελεσματικό από τη χρήση του τελεστή συνένωσης (concatenation operator), ο οποίος έχει το μειονέκτημα ότι ενώνει τα strings ανά δύο και έτσι δημιουργεί μια καθυστέρηση.

Για να φορτώσουμε μια επέκταση (extension) την ώρα της εκτέλεσης (runtime) χρησιμοποιούμε τη συνάρτηση dl(), στην οποία περνάμε το όνομα της επέκτασης που θα φορτωθεί ως τη μοναδική της παράμετρο. Το μειονέκτημα της συνάρτησης dl() είναι ότι φορτώνει δυναμικά και ξεφορτώνει την επέκταση κάθε φορά που εκτελούνται τα scripts, δηλ. δημιουργεί μια καθυστέρηση.

Ακολουθεί ένα παράδειγμα χρήσης της συνάρτησης dl() στα Windows και το Unix :

<?php

dl('php_imap.dll');      // Windows

dl('imap.so');                // Unix

?>

Στην περίπτωση που θέλουμε απλά και μόνο να δούμε αν έχει φορτωθεί μια συγκεκριμένη επέκταση ή όχι, χωρίς να ψάχνουμε την τιμή επιστροφής της συνάρτησης get_loaded_extensions(), μπορούμε να χρησιμοποιήσουμε την απλή συνάρτηση extension_loaded(), η οποία δέχεται ένα όνομα επέκτασης ως τη μοναδική της παράμετρο και επιστρέφει την τιμή true αν έχει φορτωθεί η επέκταση ή την τιμή false αν όχι.

 

Σταμάτημα της Εκτέλεσης ενός Script

void sleep ( int seconds)

void usleep ( int micro_seconds)

Όταν θέλουμε να σταματήσουμε προσωρινά (pause) την εκτέλεση ενός script, υπάρχουν δύο τρόποι για να το πετύχουμε. Μερικοί επιλέγουν τον πρώτο τρόπο και γράφουν έναν κώδικα σαν τον εξής :

<?php

$now = time();

while ($now + 4 > time()) {

// … δεν κάνει τίποτα …

}

echo "Τέλος\n";

?>

Το πρόβλημα μ’ αυτόν τον βρόχο είναι ότι η PHP θα πρέπει να περιμένει χωρίς να κάνει ουσιαστικά τίποτα. Μια πολύ καλύτερη λύση είναι να χρησιμοποιήσουμε μια από τις δύο συναρτήσεις sleep, την sleep() και την usleep(), οι οποίες δέχονται τον χρόνο που θέλουμε να σταματήσει η εκτέλεση ως τη μοναδική τους παράμετρο. Η διαφορά ανάμεσα στην sleep() και την usleep() είναι ότι η πρώτη δέχεται έναν αριθμό δευτερολέπτων ως τη μοναδική της παράμετρο, ενώ η usleep() δέχεται έναν αριθμό μικροδευτερολέπτων (microseconds), δηλ. εκατομμυριοστά του ενός δευτερολέπτου, ως τη μοναδική της παράμετρο.

Η χρήση τους είναι πολύ πιο ακριβής από τη χρήση του βρόχου με τη συνάρτηση time(), με τη διαφορά ότι η sleep() είναι καλύτερη αν δεν θέλουμε και πολύ μεγάλη ακρίβεια. Το παραπάνω script θα μπορούσε να γραφεί ως εξής :

<?php

sleep(4);

echo "Τέλος\n";

?>

Ή και έτσι :

<?php

usleep(4000000);

echo "Τέλος\n";

?>

 

Εκτέλεση Εξωτερικών Προγραμμάτων

exec ( string command [, array output [, int return_var]])

void passthru ( string command [, int return_var])

Αν και η PHP είναι μια πανίσχυρη γλώσσα προγραμματισμού, μπορεί να μας φανεί χρήσιμο το να μπορούμε να εκτελέσουμε εξωτερικά προγράμματα όταν χρειασθεί, ιδιαίτερα αν εργαζόμαστε με το Unix. Στην PHP υπάρχουν δύο σημαντικές μέθοδοι για την εκτέλεση προγραμμάτων, οι exec() και passthru(), όπου και οι δύο δέχονται μία τουλάχιστον παράμετρο, δηλ. το όνομα του προγράμματος που θέλουμε να εκτελέσουμε, αλλά η διαφορά ανάμεσά τους είναι ότι η exec() εκτελεί το πρόγραμμα και μετά στέλνει πίσω την τελευταία γραμμή εξόδου του προγράμματος ως την τιμή επιστροφής (return value).

Η συνάρτηση passthru(), από την άλλη μεριά, εκτελεί το πρόγραμμα και εκτυπώνει όλη την έξοδο που δημιουργείται. Η κλήση της exec() είναι συνήθως προτιμότερη όταν δεν μας ενδιαφέρει η έξοδος του προγράμματος, ενώ η passthru() εκτυπώνει αυτόματα την έξοδο.

Ακολουθεί ένα χαρακτηριστικό παράδειγμα :

<?php

print exec("uptime");

passthru("who");

?>

Και οι δύο παραπάνω εντολές είναι διαθέσιμες στο standard Unix. Πρέπει να έχουμε υπόψη μας ότι καθώς η εντολή uptime συνήθως επιστρέφει μία μόνο γραμμή, δεν έχει σημασία αν χρησιμοποιήσουμε την "print exec()" ή την passthru(). Αν περάσουμε μια δεύτερη και τρίτη παράμετρο στην exec(), η έξοδος της εντολής θα τοποθετηθεί στη δεύτερη παράμετρο ως ένας πίνακας (array) με μια γραμμή ανά στοιχείο και η τιμή επιστροφής της εντολής θα τοποθετηθεί στην τρίτη παράμετρο. Παρόμοια, αν περάσουμε μια δεύτερη παράμετρο στην passthru() θα γεμίσει με την τιμή επιστροφής της εντολής.

Ακολουθεί ένα παράδειγμα : 

<?php

exec("dir", $output, $return);

echo "Η εντολή dir επέστρεψε $return και έξοδο : \n";

var_dump($output);

?>

Το αποτέλεσμα από την εκτέλεση του παραπάνω script θα είναι το εξής :

Η εντολή dir επέστρεψε 1 και έξοδο : array(0) { }

Το παραπάνω παράδειγμα θα πρέπει να δουλέψει πολύ καλά στα Windows και σε πολλές εκδόσεις του Unix.

 

Συναρτήσεις Σχετικές με τη Σύνδεση του Χρήστη

int ignore_user_abort ( [bool setting])

void register_shutdown_function ( callback function)

int connection_status ( )

Τα scripts της PHP δημιουργούν έξοδο που προορίζεται για ένα πρόγραμμα-πελάτη (client), που είναι συνήθως ένας φυλλομετρητής (Web browser). Αλλά τι γίνεται αν αυτός ο φυλλομετρητής κλείσει ξαφνικά ενώ εκτελείται το script; Επίσης, πώς μπορούμε να είμαστε πάντοτε σίγουροι ότι μια συγκεκριμένη συνάρτηση εκκαθάρισης θα καλείται όταν σταματάει η εκτέλεση του script;

Η απάντηση έχει να κάνει με δύο συναρτήσεις, την ignore_user_ abort() και την register_shutdown_function(), με τις οποίες μπορούμε να συνεχίσουμε την επεξεργασία αφού ο χρήστης έχει κλείσει τον φυλλομετρητή και να προσδιορίσουμε το όνομα μιας συνάρτησης που θα εκτελεστεί όταν σταματήσει το script. Αν μεταβιβάσουμε το true στη συνάρτηση ignore_user_abort() ως τη μοναδική της παράμετρο θα καθοδηγήσει την PHP ότι το script δεν θα σταματήσει ακόμη κι αν ο χρήστης κλείσει τον φυλλομετρητή του ή πάει σ’ ένα άλλο site ή κάνει κλικ στο πλήκτρο Stop.

Αυτό είναι χρήσιμο αν έχουμε να κάνουμε κάποια σημαντική δουλειά και δεν θέλουμε να την σταματήσουμε. Μπορούμε φυσικά να μεταβιβάσουμε και την τιμή false στη συνάρτηση ignore_user_abort(), οπότε η PHP θα σταματήσει να εκτελείται όταν ο χρήστης κλείσει τη σύνδεση. Για να αντιμετωπίσουμε την περίπτωση του shutdown, υπάρχει η συνάρτηση register_shutdown_function(), που μας δίνει τη δυνατότητα να καταχωρήσουμε με την PHP μια συνάρτηση που θα εκτελεστεί όταν σταματήσει η εκτέλεση του script.

Ακολουθεί ένα παράδειγμα :

<?php

function say_goodbye() {

echo "Goodbye!\n";

}

register_shutdown_function("say_goodbye");

echo "Hello!\n";

?>

Το αποτέλεσμα από την εκτέλεση του παραπάνω script θα είναι το εξής :

Hello!

Goodbye!

 

Αλλαγή του Περιβάλλοντος Εκτέλεσης

string ini_get ( string varname)

string ini_set ( string varname, string newvalue)

void set_time_limit ( int seconds)

Ενόσω εκτελείται ένα script, μπορούμε να έχουμε έλεγχο σε κάποιες ιδιότητες του συστήματος (system attributes) που επηρεάζουν τον τρόπο εκτέλεσης του script. Με τη συνάρτηση ini_set() μπορούμε προσωρινά να αλλάξουμε το περιβάλλον εκτέλεσης, σαν να επεμβαίναμε στο αρχείο php.ini. Θα πρέπει να έχουμε υπόψη μας ότι αυτή η αλλαγή ισχύει μόνο για το τρέχον script και θα επανέλθει όταν σταματήσει η εκτέλεσή του.

Για να χρησιμοποιήσουμε τη συνάρτηση ini_set(), της μεταβιβάζουμε ένα string για την τιμή που θέλουμε να αλλάξουμε ως την πρώτη παράμετρο και τη νέα τιμή ως τη δεύτερη παράμετρο. Αν είναι επιτυχής η κλήση της, θα επιστρέψει την προηγούμενη τιμή.

Ακολουθούν μερικά παραδείγματα :

<?php

print ini_set("max_execution_time", "300") . "<br />";

print ini_set("display_errors", "0") . "<br />";

print ini_set("include_path", "0") . "<br />";

?>

Στην περίπτωση που θελήσουμε να διαβάσουμε μια τιμή του αρχείου php.ini χωρίς να την αλλάξουμε, υπάρχει η συνάρτηση ini_get(), η οποία δέχεται το όνομα της τιμής ως τη μοναδική της παράμετρο.

Ακολουθεί ένα παράδειγμα : 

<?php

print "Η εμφάνιση λαθών (display_errors) είναι ενεργή : ";

print (int) ini_get("display_errors");

?>

Με τη συνάρτηση set_time_limit() μπορούμε να ορίσουμε αυθαίρετα για πόσο χρόνο θα εκτελείται ένα script. Αυτή η τιμή ορίζεται συνήθως μέσα στο αρχείο php.ini με τη ρύθμιση max_execution_time, αλλά αυτό μπορούμε να το υπερκαλύψουμε εδώ. Η συνάρτηση δέχεται μια παράμετρο, που είναι ο αριθμός των δευτερολέπτων που θέλουμε να εκτελείται το script, ή μπορούμε να περάσουμε την τιμή 0 που σημαίνει «άσε το script να εκτελείται για όσο χρειασθεί».

Ακολουθεί ένα παράδειγμα, όπου ο χρόνος εκτέλεσης του script γίνεται ίσος με 30 δευτερόλεπτα :

set_time_limit(30);

 

Οι Συναρτήσεις Χρήστη

Παρά το γεγονός ότι η PHP περιέχει πολλές συναρτήσεις για την εκτέλεση πολλών εργασιών, είναι πολύ πιθανό να θελήσουμε να δημιουργήσουμε τις δικές μας συναρτήσεις χρήστη (user functions). Μπορούμε να δώσουμε στις συναρτήσεις μας ότι ονόματα θέλουμε με τους ίδιους κανόνες με τα ονόματα των μεταβλητών της PHP αλλά χωρίς το σύμβολο $. Θα πρέπει να έχουμε υπόψη μας βέβαια ότι δεν μπορούμε να ξαναορίσουμε τις ενσωματωμένες συναρτήσεις της PHP (built-in functions).

Η πιο απλή συνάρτηση χρήστη στην PHP είναι σαν την εξής : 

<?php

function myfunction() {

return 1;

}

print myfunction();

?>

Όπως μπορούμε να δούμε, για να ορίσουμε μια συνάρτηση χρησιμοποιούμε τη λέξη κλειδί function, ακολουθούμενη από το όνομα που θέλουμε να δώσουμε στη συνάρτηση και τον κώδικά της μέσα σε άγκιστρα. Στο συγκεκριμένο παράδειγμα η συνάρτηση περιέχει μία μόνο εντολή, την "return 1";, που θα την δούμε σε λίγο. Αφού τελειώσουμε με τον ορισμό της συνάρτησης, μπορούμε να την καλέσουμε κανονικά, όπως και να εκτυπώσουμε την τιμή επιστροφής της.

 

Οι Τιμές Επιστροφής των Συναρτήσεων

Μπορούμε να επιστρέφουμε μία μόνο τιμή από μια συνάρτηση και αυτό γίνεται με την εντολή return. Στο προηγούμενο παράδειγμα, θα μπορούσαμε να είχαμε χρησιμοποιήσει την εντολή "return 'myfunction';" ή την "return 10 + 10;", αλλά η εντολή "return 1;" είναι η πιο απλή και είναι το ίδιο σαν να είχαμε γράψει "return true;".

Μπορούμε να επιστρέψουμε όποια μεταβλητή θέλουμε, όπως integer, string ή μια σύνδεση με βάση δεδομένων (database connection) κλπ. Η εντολή "return" ορίζει την τιμή επιστροφής της συνάρτησης και εκεί σταματάει η εκτέλεση της συνάρτησης. Μπορούμε να χρησιμοποιήσουμε και την απλή εντολή "return;", που σημαίνει έξοδος από τη συνάρτηση χωρίς τιμή επιστροφής.

Ακολουθεί ένα script :

<?php

function myfunction() {

print "Μέσα στη συνάρτηση";

return 1;

print "Φεύγοντας από τη συνάρτηση …";

}

print myfunction();

?>

Το παραπάνω παράδειγμα θα εμφανίσει το μήνυμα "Μέσα στη συνάρτηση" ακολουθούμενο από το "1" και μετά το script θα σταματήσει χωρίς να εμφανίσει το κείμενο "Φεύγοντας από τη συνάρτηση …" καθώς με την εντολή "return 1" έχουμε έξοδο από τη συνάρτηση. Αν θελήσουμε να μεταβιβάσουμε περισσότερες από μία τιμές, θα πρέπει να χρησιμοποιήσουμε έναν πίνακα (array), που θα το δούμε σύντομα.

Κάτι άλλο που μπορούμε να κάνουμε είναι να επιστρέψουμε την τιμή μια εντολής υπό συνθήκη, όπως : 

return $i > 10;

Αν το $i είναι μεγαλύτερο από το 10, τότε θα επιστραφεί η τιμή 1, δηλ. σαν να είχαμε την εντολή "return 1", αλλά αν το $i είναι μικρότερο από ή ίσο με το 10, είναι σαν να είχαμε την εντολή "return 0".

 

Λήψη Παραμέτρων από Συναρτήσεις

Μπορούμε να δημιουργήσουμε συναρτήσεις που να δέχονται παραμέτρους (parameters), που είναι γνωστές και με τον όρο ορίσματα (arguments), ως εξής :

<?php

function multiply($num1, $num2) {

$total = $num1 * $num2;

return $total;

}

$mynum = multiply(2, 5);

?>

Αφού εκτελεστεί το παραπάνω script, η μεταβλητή $mynum θα είναι ίση με 10. Η συνάρτηση multiply() θα μπορούσε να περιέχει μία μόνο εντολή, την return $num1 * $num2.

 

Μεταβίβαση Παραμέτρων με Αναφορά

Για να μεταβιβάσουμε παραμέτρους με αναφορά, θα πρέπει να χρησιμοποιήσουμε τον τελεστή αναφοράς (reference operator) &. Η μεταβίβαση μιας παραμέτρου με αναφορά γίνεται στον ορισμό της συνάρτησης και όχι στην κλήση της συνάρτησης, ως εξής :

function multiply(&$num1, &$num2) {

Ακολουθεί ένα παράδειγμα :

<?php

function square1($number) {

return $number * $number;

}

$val = square1($val);

 

function square2(&$number) {

$number = $number * $number;

}

square2($val);

?>

Το πρώτο παράδειγμα μεταβιβάζει ένα αντίγραφο (copy) της τιμής της μεταβλητής $val, το οποίο υψώνεται στο τετράγωνο και επιστρέφεται το αποτέλεσμα, το οποίο και αντικαθιστά την παλιά τιμή της $val. Το δεύτερο παράδειγμα μεταβιβάζει την τιμή της μεταβλητής $val με αναφορά (by reference), η οποία τιμή τροποποιείται μέσα στη συνάρτηση, οπότε χρειάζεται μόνο να γράψουμε "square2($val);" αντί για την εκχώρηση τιμής που κάναμε στο πρώτο παράδειγμα.

Θα πρέπει να έχουμε υπόψη μας ότι αν χρησιμοποιούμε μεταβλητές με αναφορά, δεν θα πρέπει να έχουμε σταθερές τιμές στις παραμέτρους, καθώς κάτι τέτοιο δεν θα είχε νόημα, όπως το "square2(10);".

  

Οι Προκαθορισμένες Τιμές Παραμέτρων

Πολύ συχνά όταν δημιουργούμε συναρτήσεις, είναι χρήσιμο το να μπορούμε να εκχωρούμε προκαθορισμένες τιμές (default values) για παραμέτρους που δεν μεταβιβάζονται. Για να ορίσουμε τις δικές μας προκαθορισμένες παραμέτρους για μια συνάρτηση, απλά προσθέτουμε στον ορισμό της συνάρτησης και μετά από τις μεταβλητές την σταθερή τιμή που θέλουμε να έχουν, ως εξής :

<?php

function myfunction($Name = "Ligistis") {

return "Florina $Name!\n";

}

myfunction();

myfunction("Amyntaio");

myfunction("Prespes");

?>

Το παραπάνω script θα εμφανίσει τα εξής :

Florina Ligistis!

Florina Amyntaio!

Florina Prespes! 

Ας δούμε τώρα την εξής συνάρτηση :

function myfunction($FirstName, $LastName = "Smith") { }

Το όρισμα $FirstName δεν έχει προκαθορισμένη τιμή, ενώ το όρισμα $LastName έχει την προκαθορισμένη τιμή Smith. Μπορούμε, όμως, να δώσουμε προκαθορισμένες τιμές και στα δύο ορίσματα, ως εξής :

function myfunction($FirstName = "John", $LastName = "Smith") {

return "Hello, $FirstName $LastName!\n";

}

Έτσι, για να χαιρετίσουμε κάποιον που λέγεται John Smith, θα γράψουμε το εξής :

myfunction();

Ενώ για να χαιρετίσουμε κάποιον που λέγεται Tom Davies, θα γράψουμε το εξής :

myfunction("Tom", "Davies");

Τέλος, για να χαιρετίσουμε κάποιον που λέγεται Tom Smith, θα γράψουμε το εξής :

myfunction("Tom");


 

Μεταβλητός Αριθμός Παραμέτρων

int func_num_args ( )

mixed func_get_arg ( int arg_num)

array func_get_args ( )

Η συνάρτηση printf() που είδαμε νωρίτερα μπορεί να λαμβάνει έναν αυθαίρετο αριθμό παραμέτρων, όπως και η παρακάτω συνάρτηση : 

<?php

function some_func($a, $b) {

$j = 1;

}

some_func(1, 2, 3, 4, 5, 6, 7, 8);

?>

Εδώ η συνάρτηση some_func() λαμβάνει δύο μόνο παραμέτρους σύμφωνα με τον ορισμό της, τις $a και $b, αλλά τις καλέσαμε με οκτώ παραμέτρους και το script θα πρέπει να εκτελεστεί χωρίς πρόβλημα. Για βοήθεια σε τέτοιες περιπτώσεις, υπάρχουν οι εξής τρεις συναρτήσεις : func_num_args(), func_get_arg() και func_get_args(), από τις οποίες η πρώτη και η τελευταία δεν λαμβάνουν παραμέτρους.

Για να μάθουμε τον αριθμό των παραμέτρων που μεταβιβάστηκαν σε μια συνάρτηση, καλούμε τη συνάρτηση func_num_args() και διαβάζουμε την τιμή επιστροφής της. Για να μάθουμε την τιμή μιας ξεχωριστής παραμέτρους, χρησιμοποιούμε τη συνάρτηση func_get_arg() και της μεταβιβάζουμε τον αριθμό της παραμέτρου της οποίας θέλουμε να μάθουμε την τιμή. Τέλος, η συνάρτηση func_get_args() επιστρέφει έναν πίνακα (array) με τις παραμέτρους που μεταβιβάστηκαν.

Ακολουθεί ένα χαρακτηριστικό παράδειγμα : 

<?php

function some_func($a, $b) {

for ($i = 0; $i < func_num_args(); ++$i) {

$param = func_get_arg($i);

echo "Παράμετρος : $param.\n";

}

}

function some_other_func($a, $b) {

$param = func_get_args();

$param = join(", ", $param);

echo "Παράμετροι : $param.\n";

}

some_func(1, 2, 3, 4, 5, 6, 7, 8);

some_other_func(1, 2, 3, 4, 5, 6, 7, 8);

?>

Με τη βοήθεια της συνάρτησης func_num_args() μπορούμε να κάνουμε έλεγχο λαθών, όπως για παράδειγμα αν έχει δοθεί ο σωστός αριθμό των παραμέτρων. Με τη βοήθεια και της συνάρτησης func_get_arg(), μπορούμε να δημιουργήσουμε δικές μας συναρτήσεις που να δουλεύουν μ’ οποιονδήποτε αριθμό παραμέτρων.

 

Η Εμβέλεια των Μεταβλητών στις Συναρτήσεις

Όπως έχουμε ήδη αναφέρει, οι μεταβλητές (variables) που δηλώνονται εκτός των συναρτήσεων (functions) και των τάξεων (classes) θεωρούνται καθολικές (global), δηλ. είναι διαθέσιμες παντού μέσα στο script. Όμως, καθώς οι συναρτήσεις αποτελούν ανεξάρτητες ενότητες κώδικα, οι μεταβλητές τους είναι αυτόνομες και δεν επηρεάζουν τις μεταβλητές που υπάρχουν στο κυρίως script. Παρόμοια, οι μεταβλητές του κυρίως script δεν είναι πάντα διαθέσιμες μέσα στις συναρτήσεις.

Ακολουθεί ένα χαρακτηριστικό script

<?php

function myfunction() {

$a = "Florina";

}

$a = "Amyntaio";

myfunction();

print $a;

?>

Η εκτέλεση του script ξεκινά με την εντολή $a = "Amyntaio" και μετά καλείται η συνάρτηση myfunction(), η οποία δίνει στη μεταβλητή $a την τιμή "Florina" και επιστρέφει τον έλεγχο στο κυρίως script όπου εκτυπώνεται η $a.

Σχετικά με το τι θα γίνει, υπάρχουν τρεις περιπτώσεις :

1.    Το script θα εκτυπώσει το "Amyntaio"

2.    Το script θα εκτυπώσει το "Florina"

3.    Το script δεν θα εκτυπώσει τίποτα

Η πρώτη περίπτωση θα ίσχυε αν η μεταβλητή $a είχε ορισθεί εκτός της συνάρτησης, καλείτο η myfunction() για να δώσει τη δική της τιμή στην τοπική της μεταβλητή $a, η οποία και θα χανόταν μόλις τελείωνε η συνάρτηση, αφήνοντας έτσι ανεπηρέαστη την τιμή της αρχικής μεταβλητής $a. Η δεύτερη περίπτωση θα ίσχυε αν η μεταβλητή $a είχε ορισθεί εκτός της συνάρτησης, καλείτο η myfunction() για να αλλάξει το καθολικό αντίγραφο της $a και έτσι θα εκτυπωνόταν η καινούργια τιμή της $a αφότου ο έλεγχος επιστρέψει στο κυρίως script.

Η τρίτη περίπτωση θα ίσχυε αν οι μεταβλητές χανόταν κάπου ανάμεσα στις κλήσεις της συνάρτησης, κάτι απίθανο. Η δεύτερη περίπτωση θα σήμαινε ότι οι μεταβλητές που δηλώνονται καθολικά γίνονται αυτόματα διαθέσιμες μέσα στις συναρτήσεις, κάτι που ξέρουμε ότι δεν ισχύει. Συνεπώς, η πρώτη περίπτωση είναι η σωστή, δηλ. καλείται η συνάρτηση myfunction() και μη γνωρίζοντας ότι υπάρχει ήδη μια μεταβλητή με το όνομα $a, δημιουργεί μια μεταβλητή με το ίδιο όνομα στην τοπική της εμβέλεια. Μόλις τελειώσει η συνάρτηση, χάνονται όλες οι τοπικές τιμές των μεταβλητών της, αφήνοντας έτσι άθικτη την αρχική μεταβλητή $a.

 

Ο Πίνακας GLOBALS

Το θέμα είναι τι κάνουμε όταν θέλουμε να έχουμε μια καθολική μεταβλητή (global variable) μέσα σε μια συνάρτηση. Αυτό είναι εφικτό με τον πίνακα (array) $GLOBALS, ο οποίος μάς δίνει τη δυνατότητα να έχουμε πρόσβαση σε καθολικές μεταβλητές ακόμα και μέσα από συναρτήσεις. Όλες οι μεταβλητές που δηλώνονται στην καθολική εμβέλεια βρίσκονται στον πίνακα $GLOBALS, στον οποίο μπορούμε να έχουμε πρόσβαση από οπουδήποτε μέσα στο script.

Ακολουθεί ένα χαρακτηριστικό script

<?php

function myfunction() {

$GLOBALS['a'] = "Florina";

}

$a = "Amyntaio";

myfunction();

print $a;

?>

Ο παραπάνω κώδικας θα εκτυπώσει το κείμενο "Florina" και αυτό γιατί η συνάρτηση myfunction() θα αλλάξει την καθολική μεταβλητή $a και η αλλαγή θα ισχύει και όταν ο έλεγχος επιστρέψει στο κυρίως script.

Μπορούμε να διαβάσουμε μεταβλητές και ως εξής : 

$localbar = $GLOBALS['a'];

Στην PHP μπορούμε να χρησιμοποιήσουμε την δεσμευμένη λέξη GLOBAL και ως εξής :

function myfunc() {

GLOBAL $a, $b, $c;

++$b;

}

Η παραπάνω συνάρτηση διαβάζει τις καθολικές μεταβλητές $a, $b και $c και η εντολή ++$b αυξάνει την τιμή της $b κατά 1, κάτι που επηρεάζει και την καθολική τιμή της μεταβλητής.

 

Οι Αναδρομικές Συναρτήσεις

Μερικές φορές ο ευκολότερος τρόπος για να λύσουμε ένα πρόβλημα είναι να κάνουμε μια συνάρτηση να καλεί τον εαυτό της, μια τεχνική που είναι γνωστή με τον όρο αναδρομική κλήση συνάρτησης (recursive function calling). Ο υπολογισμός του παραγοντικού (factorial) είναι ένα κοινό πρόβλημα, όπου για παράδειγμα το παραγοντικό του 6 είναι το 6 * 5 * 4 * 3 * 2 * 1, ή 720, και παριστάνεται με τον συμβολισμό 6!

Έτσι, αν δοθεί ότι το παραγοντικό του 6 (6!) είναι ίσο με 720, το ερώτημα είναι ποιο είναι το παραγοντικό του 7 και πώς σχετίζεται με το 6!; Το 7! είναι ίσο με 7 * 6!, που σημαίνει ότι εφόσον έχουμε υπολογίσει το 6!, απαιτείται ένας απλός πολλαπλασιασμός του αποτελέσματος με το 7 για να πάρουμε το 7! Αυτή η εξίσωση παριστάνεται ως εξής : n! = n * ((n - 1)!), δηλ. το παραγοντικό ενός αριθμού είναι ίσο με το γινόμενο του ίδιου του αριθμού με το παραγοντικό του αριθμού που είναι μικρότερος κατά μία μονάδα.

Αυτό που χρειαζόμαστε είναι μια συνάρτηση που θα δέχεται ως είσοδο έναν ακέραιο και αν αυτός ο ακέραιος δεν είναι ίσος με το 0, θα καλεί την ίδια τη συνάρτηση μεταβιβάζοντας τον ίδιο τον αριθμό που δέχθηκε μειωμένο κατά ένα και μετά θα πολλαπλασιάζει το αποτέλεσμα με τον αριθμό.

Η συνάρτηση για τον υπολογισμό του παραγοντικού αποτελείται από δύο μόνο γραμμές κώδικα, ως εξής : 

<?php

function factorial($number) {

if ($number == 0)

return 1;

return $number * factorial($number - 1);

}

print factorial(6);

?>

Ο παραπάνω κώδικας θα εκτυπώσει το 720.

 

Συναρτήσεις για Χειρισμό Συναρτήσεων

bool is_callable ( mixed function_name [, bool syntax_only [, string callable_name]])

mixed call_user_func ( callback function [, mixed parameter [, mixed ...]])

mixed call_user_func_array ( callback function [, array parameters])

Όπως έχουμε ήδη δει, η PHP διαθέτει μεταβλητές μεταβλητές (variable variables), έτσι δεν είναι έκπληξη να πούμε ότι διαθέτει και μεταβλητές συναρτήσεις (variable functions). Αυτό σημαίνει ότι μπορούμε να γράψουμε κώδικα σαν τον εξής : 

<?php

$func = "sqrt";

print $func(49);

?>

Η PHP βλέπει ότι καλούμε μια συνάρτηση χρησιμοποιώντας μια μεταβλητή, ψάχνει την τιμή της μεταβλητής και μετά καλεί τη συνάρτηση. Ο παραπάνω κώδικας θα επιστρέψει την τιμή 7, που είναι η τετραγωνική ρίζα του 49. Καθώς οι μεταβλητές συναρτήσεις δεν είναι και τόσο συνήθεις και είναι εύκολο να γίνουν λάθη, υπάρχει μια ειδική συνάρτηση της PHP, η is_callable(), η οποία λαμβάνει ένα string ως την πρώτη της παράμετρο και επιστρέφει την τιμή true αν το string περιέχει ένα όνομα συνάρτησης που να μπορεί να κληθεί με μια μεταβλητή συνάρτηση. Έτσι, μπορούμε να γράψουμε το παραπάνω script ως εξής :

<?php

$func = "sqrt";

if (is_callable($func)) {

print $func(49);

}

?>

Ως μια εναλλακτική λύση στις μεταβλητές συναρτήσεις (variable functions), μπορούμε να χρησιμοποιήσουμε και τις συναρτήσεις call_user_func() και call_user_func_array(), που λαμβάνουν ως την πρώτη τους παράμετρο τη συνάρτηση που θέλουμε να καλέσουμε. Η διαφορά ανάμεσα στις δύο είναι ότι η call_user_func() δέχεται τις παραμέτρους που θα μεταβιβάσει στη μεταβλητή συνάρτηση ως πολλαπλές παραμέτρους, ενώ η call_user_func_array() δέχεται έναν πίνακα (array) από παραμέτρους ως τη δεύτερή της παράμετρο.

Το επόμενο script δείχνει και τις δύο αυτές συναρτήσεις να κάνουν μια παρόμοια λειτουργία, αντικαθιστώντας το κείμενο "monkeys" με το "giraffes" σε μια πρόταση, χρησιμοποιώντας τη συνάρτηση str_replace() :

<?php

$func = "str_replace";

$output_single = call_user_func($func, "monkeys", "giraffes", "Hundreds and thousands of monkeys\n");

$params = array("monkeys", "giraffes", "Hundreds and thousands of monkeys\n");

$output_array = call_user_func_array($func, $params);

echo $output_single;

echo $output_array;

?>

Αν και η συνάρτηση call_user_func() είναι το ίδιο πράγμα με το να χρησιμοποιούμε μια μεταβλητή συνάρτηση, η συνάρτηση call_user_func_array() είναι πολύ χρήσιμη για συναρτήσεις που είναι αρκετά πολύπλοκες.

 

Μια Σύντομη Εισαγωγή στα Ticks

void register_tick_function ( callback function [, mixed arguments])

void unregister_tick_function ( string function_name)

Υπάρχει μια τελευταία ομάδα συναρτήσεων που θα πρέπει να έχουμε υπόψη μας, με πρώτη την declare(), η οποία δεν είναι στην ουσία μια συνάρτηση αλλά μια δομή γλώσσας (language construct), που συμπεριφέρεται παράξενα, χρησιμοποιείται σπάνια και η πιο κοινή χρήση της είναι για τον έλεγχο των διαδικασιών (process control).

Για να το πούμε με απλά λόγια, ένα tick είναι ένα συμβάν (event) που λαμβάνει χώρα μέσα στην PHP κάθε φορά που έχει εκτελεστεί ένας συγκεκριμένος αριθμός εντολών. Μπορούμε να ελέγχουμε το πόσες εντολές χρειάζονται για να ενεργοποιηθεί ένα tick χρησιμοποιώντας τη συνάρτηση declare() και μπορούμε να ορίσουμε τις συναρτήσεις που θα εκτελούνται όταν συμβεί ένα tick χρησιμοποιώντας τη συνάρτηση register_tick_function().

Ακολουθεί ένα παράδειγμα : 

<?php

function myfunc() {

print "In tick func\n";

}

register_tick_function("myfunc");

declare(ticks=10) {

for($i = 0; $i < 20; ++$i) {

print "Hello\n";

}

}

declare(ticks=4) {

for($i = 0; $i < 20; ++$i) {

print "Hello\n";

}

}

?>

Βλέπουμε ότι η συνάρτηση myfunc() έχει ορισθεί ως η συνάρτηση tick, που σημαίνει ότι θα εκτελεστεί κάθε φορά που συμβαίνει ένα tick. Στην πρώτη χρήση της συνάρτησης declare() το "ticks" τίθεται ίσο με 10 και ανοίγει ένα κομμάτι κώδικα, που σημαίνει ότι μέχρι να κλείσει το μπλοκ του κώδικα, τα ticks θα συμβαίνουν κάθε 10 εντολές.

Μέσα στην εντολή declare() υπάρχει ένας βρόχος που εκτυπώνει το κείμενο "Hello" 20 φορές, έτσι νομίζουμε ότι η συνάρτηση myfunc() θα κληθεί 2 φορές επειδή 20 / 10 = 2. Όμως, η συνάρτηση myfunc() θα κληθεί 4 φορές επειδή η αύξηση του μετρητή αποτελεί κι αυτή μια εσωτερική εντολή και έτσι ο συνολικός αριθμός των εντολών φθάνει τις 40.

Αμέσως μετά από το πρώτο μπλοκ declare() υπάρχει κι ένα δεύτερο μπλοκ όπου το ticks είναι ίσο με 4, που σημαίνει ότι οι συναρτήσεις tick θα εκτελούνται πιο συχνά. Για να καταργήσουμε τη συσχέτιση μιας συνάρτησης tick, χρησιμοποιούμε τη συνάρτηση unregister_tick_function(). Μπορούμε να περάσουμε και διάφορες παραμέτρους που θέλουμε να σταλούν στις συναρτήσεις tick, όπως φαίνεται στο επόμενο κομμάτι κώδικα :

<?php

function myfunc($param1, $param2) {

echo "In first tick function with params $param1 $param2\n";

}

function myfunc2($param1, $param2, $param3) {

echo "In second tick function with params $param1 $param2 $param3\n";

}

 

function myfunc3($param1) {

echo "In third tick function with params $param1\n";

}

register_tick_function("myfunc", "hello", "world");

register_tick_function("myfunc2", "how", "are", "you?");

register_tick_function("myfunc3", "goodbye!");

unregister_tick_function("myfunc2");

declare(ticks=10);

for($i = 0; $i < 20; ++$i) {

echo "Hello\n";

}

?>
 

back.gif (9867 bytes)

Επιστροφή