German (Deutsch) translation by Nikol Angelowa (you can also view the original English article)
Zweimal im Monat besuchen wir einige der Lieblingsbeiträge unserer Leser aus der gesamten Geschichte von Nettuts+.
Selbst nachdem wir jahrelang PHP verwendet haben, stoßen wir auf Funktionen und Merkmale, die wir nicht kannten. Einige davon können sehr nützlich sein, werden aber nicht ausreichend genutzt. Vor diesem Hintergrund habe ich eine Liste von neun unglaublich nützlichen PHP-Funktionen und -Funktionen zusammengestellt, mit denen Sie vertraut sein sollten.
1. Funktionen mit beliebiger Anzahl von Argumenten
Möglicherweise wissen Sie bereits, dass Sie mit PHP Funktionen mit optionalen Argumenten definieren können. Es gibt aber auch eine Methode, um eine völlig beliebige Anzahl von Funktionsargumenten zuzulassen.
Hier ist zunächst ein Beispiel mit nur optionalen Argumenten:
1 |
// function with 2 optional arguments
|
2 |
function foo($arg1 = '', $arg2 = '') { |
3 |
|
4 |
echo "arg1: $arg1\n"; |
5 |
echo "arg2: $arg2\n"; |
6 |
|
7 |
}
|
8 |
|
9 |
|
10 |
foo('hello','world'); |
11 |
/* prints:
|
12 |
arg1: hello
|
13 |
arg2: world
|
14 |
*/
|
15 |
|
16 |
foo(); |
17 |
/* prints:
|
18 |
arg1:
|
19 |
arg2:
|
20 |
*/
|
Nun wollen wir sehen, wie wir eine Funktion erstellen können, die eine beliebige Anzahl von Argumenten akzeptiert. Dieses Mal werden wir func_get_args() verwenden:
1 |
// yes, the argument list can be empty
|
2 |
function foo() { |
3 |
|
4 |
// returns an array of all passed arguments
|
5 |
$args = func_get_args(); |
6 |
|
7 |
foreach ($args as $k => $v) { |
8 |
echo "arg".($k+1).": $v\n"; |
9 |
}
|
10 |
|
11 |
}
|
12 |
|
13 |
foo(); |
14 |
/* prints nothing */
|
15 |
|
16 |
foo('hello'); |
17 |
/* prints
|
18 |
arg1: hello
|
19 |
*/
|
20 |
|
21 |
foo('hello', 'world', 'again'); |
22 |
/* prints
|
23 |
arg1: hello
|
24 |
arg2: world
|
25 |
arg3: again
|
26 |
*/
|
2. Verwenden von Glob() zum Suchen von Dateien
Viele PHP-Funktionen haben lange und beschreibende Namen. Es kann jedoch schwierig sein zu sagen, was eine Funktion namens glob() tut, es sei denn, Sie kennen diesen Begriff bereits von einer anderen Stelle.
Stellen Sie sich das wie eine leistungsfähigere Version der Funktion scandir() vor. Sie können mithilfe von Mustern nach Dateien suchen.
1 |
// get all php files
|
2 |
$files = glob('*.php'); |
3 |
|
4 |
print_r($files); |
5 |
/* output looks like:
|
6 |
Array
|
7 |
(
|
8 |
[0] => phptest.php
|
9 |
[1] => pi.php
|
10 |
[2] => post_output.php
|
11 |
[3] => test.php
|
12 |
)
|
13 |
*/
|
Sie können mehrere Dateitypen so abrufen:
1 |
// get all php files AND txt files
|
2 |
$files = glob('*.{php,txt}', GLOB_BRACE); |
3 |
|
4 |
print_r($files); |
5 |
/* output looks like:
|
6 |
Array
|
7 |
(
|
8 |
[0] => phptest.php
|
9 |
[1] => pi.php
|
10 |
[2] => post_output.php
|
11 |
[3] => test.php
|
12 |
[4] => log.txt
|
13 |
[5] => test.txt
|
14 |
)
|
15 |
*/
|
Beachten Sie, dass die Dateien abhängig von Ihrer Abfrage tatsächlich mit einem Pfad zurückgegeben werden können:
1 |
$files = glob('../images/a*.jpg'); |
2 |
|
3 |
print_r($files); |
4 |
/* output looks like:
|
5 |
Array
|
6 |
(
|
7 |
[0] => ../images/apple.jpg
|
8 |
[1] => ../images/art.jpg
|
9 |
)
|
10 |
*/
|
Wenn Sie den vollständigen Pfad zu jeder Datei erhalten möchten, können Sie einfach die Funktion realpath() für die zurückgegebenen Werte aufrufen:
1 |
$files = glob('../images/a*.jpg'); |
2 |
|
3 |
// applies the function to each array element
|
4 |
$files = array_map('realpath',$files); |
5 |
|
6 |
print_r($files); |
7 |
/* output looks like:
|
8 |
Array
|
9 |
(
|
10 |
[0] => C:\wamp\www\images\apple.jpg
|
11 |
[1] => C:\wamp\www\images\art.jpg
|
12 |
)
|
13 |
*/
|
3. Informationen zur Speichernutzung
Wenn Sie die Speichernutzung Ihrer Skripte beobachten, können Sie Ihren Code möglicherweise besser optimieren.
PHP hat einen Garbage Collector und einen ziemlich komplexen Speichermanager. Die Menge an Speicher, die von Ihrem Skript verwendet wird. kann während der Ausführung eines Skripts auf und ab gehen. Um die aktuelle Speichernutzung abzurufen, können wir die Funktion memory_get_usage() verwenden. Um die höchste Speichermenge zu erhalten, die zu einem beliebigen Zeitpunkt verwendet wird, können wir die Funktion memory_get_peak_usage() verwenden.
1 |
echo "Initial: ".memory_get_usage()." bytes \n"; |
2 |
/* prints
|
3 |
Initial: 361400 bytes
|
4 |
*/
|
5 |
|
6 |
// let's use up some memory
|
7 |
for ($i = 0; $i < 100000; $i++) { |
8 |
$array []= md5($i); |
9 |
}
|
10 |
|
11 |
// let's remove half of the array
|
12 |
for ($i = 0; $i < 100000; $i++) { |
13 |
unset($array[$i]); |
14 |
}
|
15 |
|
16 |
echo "Final: ".memory_get_usage()." bytes \n"; |
17 |
/* prints
|
18 |
Final: 885912 bytes
|
19 |
*/
|
20 |
|
21 |
echo "Peak: ".memory_get_peak_usage()." bytes \n"; |
22 |
/* prints
|
23 |
Peak: 13687072 bytes
|
24 |
*/
|
4. Informationen zur CPU-Auslastung
Dafür verwenden wir die Funktion getrusage(). Beachten Sie, dass dies auf Windows-Plattformen nicht verfügbar ist.
1 |
print_r(getrusage()); |
2 |
/* prints
|
3 |
Array
|
4 |
(
|
5 |
[ru_oublock] => 0
|
6 |
[ru_inblock] => 0
|
7 |
[ru_msgsnd] => 2
|
8 |
[ru_msgrcv] => 3
|
9 |
[ru_maxrss] => 12692
|
10 |
[ru_ixrss] => 764
|
11 |
[ru_idrss] => 3864
|
12 |
[ru_minflt] => 94
|
13 |
[ru_majflt] => 0
|
14 |
[ru_nsignals] => 1
|
15 |
[ru_nvcsw] => 67
|
16 |
[ru_nivcsw] => 4
|
17 |
[ru_nswap] => 0
|
18 |
[ru_utime.tv_usec] => 0
|
19 |
[ru_utime.tv_sec] => 0
|
20 |
[ru_stime.tv_usec] => 6269
|
21 |
[ru_stime.tv_sec] => 0
|
22 |
)
|
23 |
|
24 |
*/
|
Das sieht vielleicht etwas kryptisch aus, es sei denn, Sie haben bereits einen Hintergrund in der Systemadministration. Hier ist die Erklärung für jeden Wert (Sie müssen sich diese nicht merken):
- ru_oublock: Blockausgabeoperationen
- ru_inblock: Blockeingabeoperationen
- ru_msgsnd: Nachrichten gesendet
- ru_msgrcv: Nachrichten empfangen
- ru_maxrss: maximale Größe des residenten Sets
- ru_ixrss: Integrierte Größe des gemeinsam genutzten Speichers
- ru_idrss: Integrale nicht gemeinsam genutzte Datengröße
- ru_minflt: Seite wird zurückgefordert
- ru_majflt: Seitenfehler
- ru_nsignals: empfangene Signale
- ru_nvcsw: freiwillige Kontextwechsel
- ru_nivcsw: unfreiwillige Kontextwechsel
- ru_nswap: Swaps
- ru_utime.tv_usec: Verwendete Benutzerzeit (Mikrosekunden)
- ru_utime.tv_sec: Verwendete Benutzerzeit (Sekunden)
- ru_stime.tv_usec: Verwendete Systemzeit (Mikrosekunden)
- ru_stime.tv_sec: Verwendete Systemzeit (Sekunden)
Um zu sehen, wie viel CPU-Leistung das Skript verbraucht hat, müssen wir uns die Werte für "Benutzerzeit" und "Systemzeit" ansehen. Die Sekunden- und Mikrosekundenabschnitte werden standardmäßig separat bereitgestellt. Sie können den Mikrosekundenwert durch 1 Million teilen und zum Sekundenwert addieren, um die Gesamtsekunde als Dezimalzahl zu erhalten.
Sehen wir uns ein Beispiel an:
1 |
// sleep for 3 seconds (non-busy)
|
2 |
sleep(3); |
3 |
|
4 |
$data = getrusage(); |
5 |
echo "User time: ". |
6 |
($data['ru_utime.tv_sec'] + |
7 |
$data['ru_utime.tv_usec'] / 1000000); |
8 |
echo "System time: ". |
9 |
($data['ru_stime.tv_sec'] + |
10 |
$data['ru_stime.tv_usec'] / 1000000); |
11 |
|
12 |
/* prints
|
13 |
User time: 0.011552
|
14 |
System time: 0
|
15 |
*/
|
Obwohl die Ausführung des Skripts etwa 3 Sekunden dauerte, war die CPU-Auslastung sehr, sehr gering. Da das Skript während des Ruhezustands tatsächlich keine CPU-Ressourcen verbraucht. Es gibt viele andere Aufgaben, die möglicherweise in Echtzeit ausgeführt werden, jedoch möglicherweise keine CPU-Zeit benötigen, z. B. das Warten auf Festplattenvorgänge. Wie Sie sehen, sind die CPU-Auslastung und die tatsächliche Laufzeit nicht immer gleich.
Hier ist ein weiteres Beispiel:
1 |
// loop 10 million times (busy)
|
2 |
for($i=0;$i<10000000;$i++) { |
3 |
|
4 |
}
|
5 |
|
6 |
$data = getrusage(); |
7 |
echo "User time: ". |
8 |
($data['ru_utime.tv_sec'] + |
9 |
$data['ru_utime.tv_usec'] / 1000000); |
10 |
echo "System time: ". |
11 |
($data['ru_stime.tv_sec'] + |
12 |
$data['ru_stime.tv_usec'] / 1000000); |
13 |
|
14 |
/* prints
|
15 |
User time: 1.424592
|
16 |
System time: 0.004204
|
17 |
*/
|
Dies dauerte ungefähr 1,4 Sekunden CPU-Zeit, fast die gesamte Benutzerzeit, da keine Systemaufrufe stattfanden.
Systemzeit ist die Zeit, die die CPU damit verbringt, Systemaufrufe für den Kernel im Namen des Programms auszuführen. Hier ist ein Beispiel dafür:
1 |
$start = microtime(true); |
2 |
// keep calling microtime for about 3 seconds
|
3 |
while(microtime(true) - $start < 3) { |
4 |
|
5 |
}
|
6 |
|
7 |
$data = getrusage(); |
8 |
echo "User time: ". |
9 |
($data['ru_utime.tv_sec'] + |
10 |
$data['ru_utime.tv_usec'] / 1000000); |
11 |
echo "System time: ". |
12 |
($data['ru_stime.tv_sec'] + |
13 |
$data['ru_stime.tv_usec'] / 1000000); |
14 |
|
15 |
/* prints
|
16 |
User time: 1.088171
|
17 |
System time: 1.675315
|
18 |
*/
|
Jetzt haben wir ziemlich viel Systemzeitverbrauch. Dies liegt daran, dass das Skript die Funktion microtime() viele Male aufruft, wodurch über das Betriebssystem eine Anforderung zum Abrufen der Zeit ausgeführt wird.
Möglicherweise stellen Sie auch fest, dass sich die Zahlen nicht ganz auf 3 Sekunden summieren. Dies liegt daran, dass wahrscheinlich auch andere Prozesse auf dem Server vorhanden waren und das Skript während der gesamten Dauer der 3 Sekunden keine 100% ige CPU verwendete.
5. Magische Konstanten
PHP bietet nützliche magische Konstanten zum Abrufen der aktuellen Zeilennummer (__LINE__), des Dateipfads (__FILE__), des Verzeichnispfads (__DIR__), des Funktionsnamens (__FUNCTION__), des Klassennamens (__CLASS__), des Methodennamens (__METHOD__) und des Namespace (__NAMESPACE__).
Wir werden nicht jeden dieser Punkte in diesem Artikel behandeln, aber ich werde Ihnen einige Anwendungsfälle zeigen.
Wenn Sie andere Skripte einfügen, empfiehlt es sich, die Konstante __FILE__ (oder auch __DIR__ ab PHP 5.3) zu verwenden:
1 |
// this is relative to the loaded script's path
|
2 |
// it may cause problems when running scripts from different directories
|
3 |
require_once('config/database.php'); |
4 |
|
5 |
// this is always relative to this file's path
|
6 |
// no matter where it was included from
|
7 |
require_once(dirname(__FILE__) . '/config/database.php'); |
Die Verwendung von __LINE__ erleichtert das Debuggen. Sie können die Zeilennummern aufspüren:
1 |
// some code
|
2 |
// ...
|
3 |
my_debug("some debug message", __LINE__); |
4 |
/* prints
|
5 |
Line 4: some debug message
|
6 |
*/
|
7 |
|
8 |
// some more code
|
9 |
// ...
|
10 |
my_debug("another debug message", __LINE__); |
11 |
/* prints
|
12 |
Line 11: another debug message
|
13 |
*/
|
14 |
|
15 |
function my_debug($msg, $line) { |
16 |
echo "Line $line: $msg\n"; |
17 |
}
|
6. Generieren eindeutiger IDs
Es kann Situationen geben, in denen Sie eine eindeutige Zeichenfolge generieren müssen. Ich habe viele Leute gesehen, die die Funktion md5() dafür verwenden, obwohl sie nicht genau für diesen Zweck gedacht ist:
1 |
// generate unique string
|
2 |
echo md5(time() . mt_rand(1,1000000)); |
Es gibt tatsächlich eine PHP-Funktion namens uniqid(), die dafür verwendet werden soll.
1 |
// generate unique string
|
2 |
echo uniqid(); |
3 |
/* prints
|
4 |
4bd67c947233e
|
5 |
*/
|
6 |
|
7 |
// generate another unique string
|
8 |
echo uniqid(); |
9 |
/* prints
|
10 |
4bd67c9472340
|
11 |
*/
|
Möglicherweise stellen Sie fest, dass die Zeichenfolgen zwar eindeutig sind, für die ersten Zeichen jedoch ähnlich erscheinen. Dies liegt daran, dass die generierte Zeichenfolge mit der Serverzeit zusammenhängt. Dies hat tatsächlich einen schönen Nebeneffekt, da jede neu generierte ID später in alphabetischer Reihenfolge angezeigt wird, sodass sie sortiert werden können.
Um die Wahrscheinlichkeit eines Duplikats zu verringern, können Sie ein Präfix oder den zweiten Parameter übergeben, um die Entropie zu erhöhen:
1 |
// with prefix
|
2 |
echo uniqid('foo_'); |
3 |
/* prints
|
4 |
foo_4bd67d6cd8b8f
|
5 |
*/
|
6 |
|
7 |
// with more entropy
|
8 |
echo uniqid('',true); |
9 |
/* prints
|
10 |
4bd67d6cd8b926.12135106
|
11 |
*/
|
12 |
|
13 |
// both
|
14 |
echo uniqid('bar_',true); |
15 |
/* prints
|
16 |
bar_4bd67da367b650.43684647
|
17 |
*/
|
Diese Funktion generiert kürzere Zeichenfolgen als md5(), wodurch Sie auch Platz sparen.
7. Serialisierung
Mussten Sie jemals eine komplexe Variable in einer Datenbank oder einer Textdatei speichern? Sie müssen keine ausgefallene Lösung finden, um Ihre Arrays oder Objekte in formatierte Zeichenfolgen zu konvertieren, da PHP bereits über Funktionen für diesen Zweck verfügt.
Es gibt zwei beliebte Methoden zum Serialisieren von Variablen. Hier ist ein Beispiel, das serialize() und unserialize() verwendet:
1 |
// a complex array
|
2 |
$myvar = array( |
3 |
'hello', |
4 |
42, |
5 |
array(1,'two'), |
6 |
'apple'
|
7 |
);
|
8 |
|
9 |
// convert to a string
|
10 |
$string = serialize($myvar); |
11 |
|
12 |
echo $string; |
13 |
/* prints
|
14 |
a:4:{i:0;s:5:"hello";i:1;i:42;i:2;a:2:{i:0;i:1;i:1;s:3:"two";}i:3;s:5:"apple";}
|
15 |
*/
|
16 |
|
17 |
// you can reproduce the original variable
|
18 |
$newvar = unserialize($string); |
19 |
|
20 |
print_r($newvar); |
21 |
/* prints
|
22 |
Array
|
23 |
(
|
24 |
[0] => hello
|
25 |
[1] => 42
|
26 |
[2] => Array
|
27 |
(
|
28 |
[0] => 1
|
29 |
[1] => two
|
30 |
)
|
31 |
|
32 |
[3] => apple
|
33 |
)
|
34 |
*/
|
Dies war die native PHP-Serialisierungsmethode. Da JSON in den letzten Jahren so populär geworden ist, haben sie beschlossen, Unterstützung für PHP 5.2 hinzuzufügen. Jetzt können Sie auch die Funktionen json_encode() und json_decode() verwenden:
1 |
// a complex array
|
2 |
$myvar = array( |
3 |
'hello', |
4 |
42, |
5 |
array(1,'two'), |
6 |
'apple'
|
7 |
);
|
8 |
|
9 |
// convert to a string
|
10 |
$string = json_encode($myvar); |
11 |
|
12 |
echo $string; |
13 |
/* prints
|
14 |
["hello",42,[1,"two"],"apple"]
|
15 |
*/
|
16 |
|
17 |
// you can reproduce the original variable
|
18 |
$newvar = json_decode($string); |
19 |
|
20 |
print_r($newvar); |
21 |
/* prints
|
22 |
Array
|
23 |
(
|
24 |
[0] => hello
|
25 |
[1] => 42
|
26 |
[2] => Array
|
27 |
(
|
28 |
[0] => 1
|
29 |
[1] => two
|
30 |
)
|
31 |
|
32 |
[3] => apple
|
33 |
)
|
34 |
*/
|
Es ist kompakter und am besten mit Javascript und vielen anderen Sprachen kompatibel. Bei komplexen Objekten können jedoch einige Informationen verloren gehen.
8. Komprimieren von Saiten
Wenn wir über Komprimierung sprechen, denken wir normalerweise an Dateien wie ZIP-Archive. Es ist möglich, lange Zeichenfolgen in PHP zu komprimieren, ohne Archivdateien einzubeziehen.
Im folgenden Beispiel werden wir die Funktionen gzcompress() und gzuncompress() verwenden:
1 |
$string = |
2 |
"Lorem ipsum dolor sit amet, consectetur
|
3 |
adipiscing elit. Nunc ut elit id mi ultricies
|
4 |
adipiscing. Nulla facilisi. Praesent pulvinar,
|
5 |
sapien vel feugiat vestibulum, nulla dui pretium orci,
|
6 |
non ultricies elit lacus quis ante. Lorem ipsum dolor
|
7 |
sit amet, consectetur adipiscing elit. Aliquam
|
8 |
pretium ullamcorper urna quis iaculis. Etiam ac massa
|
9 |
sed turpis tempor luctus. Curabitur sed nibh eu elit
|
10 |
mollis congue. Praesent ipsum diam, consectetur vitae
|
11 |
ornare a, aliquam a nunc. In id magna pellentesque
|
12 |
tellus posuere adipiscing. Sed non mi metus, at lacinia
|
13 |
augue. Sed magna nisi, ornare in mollis in, mollis
|
14 |
sed nunc. Etiam at justo in leo congue mollis.
|
15 |
Nullam in neque eget metus hendrerit scelerisque
|
16 |
eu non enim. Ut malesuada lacus eu nulla bibendum
|
17 |
id euismod urna sodales. "; |
18 |
|
19 |
$compressed = gzcompress($string); |
20 |
|
21 |
echo "Original size: ". strlen($string)."\n"; |
22 |
/* prints
|
23 |
Original size: 800
|
24 |
*/
|
25 |
|
26 |
|
27 |
|
28 |
echo "Compressed size: ". strlen($compressed)."\n"; |
29 |
/* prints
|
30 |
Compressed size: 418
|
31 |
*/
|
32 |
|
33 |
// getting it back
|
34 |
$original = gzuncompress($compressed); |
Wir konnten eine Größenreduzierung von fast 50% erzielen. Auch die Funktionen gzencode() und gzdecode() erzielen ähnliche Ergebnisse, indem sie einen anderen Komprimierungsalgorithmus verwenden.
9. Abschaltfunktion registrieren
Es gibt eine Funktion namens register_shutdown_function(), mit der Sie Code ausführen können, bevor das Skript ausgeführt wird.
Stellen Sie sich vor, Sie möchten am Ende Ihrer Skriptausführung einige Benchmark-Statistiken erfassen, z. B. wie lange die Ausführung gedauert hat:
1 |
// capture the start time
|
2 |
$start_time = microtime(true); |
3 |
|
4 |
// do some stuff
|
5 |
// ...
|
6 |
|
7 |
// display how long the script took
|
8 |
echo "execution took: ". |
9 |
(microtime(true) - $start_time). |
10 |
" seconds."; |
Auf den ersten Blick mag dies trivial erscheinen. Sie fügen den Code einfach ganz unten im Skript hinzu und er wird ausgeführt, bevor er abgeschlossen ist. Wenn Sie jedoch jemals die Funktion exit() aufrufen, wird dieser Code niemals ausgeführt. Wenn ein schwerwiegender Fehler vorliegt oder wenn das Skript vom Benutzer beendet wird (durch Drücken der Stopp-Taste im Browser), wird es möglicherweise erneut nicht ausgeführt.
Wenn Sie register_shutdown_function() verwenden, wird Ihr Code ausgeführt, unabhängig davon, warum das Skript nicht mehr ausgeführt wird:
1 |
$start_time = microtime(true); |
2 |
|
3 |
register_shutdown_function('my_shutdown'); |
4 |
|
5 |
// do some stuff
|
6 |
// ...
|
7 |
|
8 |
|
9 |
function my_shutdown() { |
10 |
global $start_time; |
11 |
|
12 |
echo "execution took: ". |
13 |
(microtime(true) - $start_time). |
14 |
" seconds."; |
15 |
}
|
Abschluss
Kennen Sie andere PHP-Funktionen, die nicht allgemein bekannt sind, aber sehr nützlich sein können? Bitte teilen Sie uns in den Kommentaren. Und danke fürs Lesen!



