mirror of
https://github.com/php/doc-pl.git
synced 2026-04-24 15:28:04 +02:00
1749 lines
48 KiB
XML
1749 lines
48 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- EN-Revision: f4f96ef8b2a95283c92ea2183fe1dedf06f3ad22 Maintainer: sobak Status: ready -->
|
|
<!-- CREDITS: cyb0org, pirate -->
|
|
<chapter xml:id="language.functions" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<title>Funkcje</title>
|
|
|
|
<sect1 xml:id="functions.user-defined">
|
|
<title>Funkcje definiowane przez użytkownika</title>
|
|
|
|
<para>
|
|
Funkcja może być definiowana przy użyciu następującej składni:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Pseudokod demonstrujący użycie funkcji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
|
|
{
|
|
echo "Przykładowa funkcja.\n";
|
|
return $retval;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
Każdy poprawny kod może być użyty wewnątrz funkcji,
|
|
łącznie z definicjami innych funkcji i
|
|
<link linkend="language.oop5.basic.class">klas</link>.
|
|
</simpara>
|
|
<para>
|
|
Nazwy funkcji obowiązują identyczne zasady, jak w przypadku wszystkich innych etykiet w PHP.
|
|
Poprawna nazwa funkcji zaczyna się od litery lub podkreślnika, po których następuje
|
|
dowolna ilość liter, cyfr i podkreślników. Jako wyrażenie regularne, określone
|
|
zostałoby to następująco:
|
|
<code>'^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
|
|
</para>
|
|
&tip.userlandnaming;
|
|
<simpara>
|
|
Funkcje nie muszą być zdefiniowane przed odniesieniem się do nich,
|
|
<emphasis>oprócz</emphasis> sytuacji, w których funkcja jest
|
|
zdefiniowana warunkowo jak w dwóch poniższych przykładach.
|
|
</simpara>
|
|
<para>
|
|
Kiedy funkcja jest zdefiniowana warunkowo, jak w dwóch poniższych przykładach,
|
|
jej definicja musi być przetworzona <emphasis>przed</emphasis>
|
|
jej wywołaniem.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Funkcje zdefiniowane warunkowo</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$makefoo = true;
|
|
|
|
/* Nie możemy tu wywołać foo()
|
|
ponieważ jeszcze nie istnieje,
|
|
ale możemy wywołać bar() */
|
|
|
|
bar();
|
|
|
|
if ($makefoo) {
|
|
function foo()
|
|
{
|
|
echo "Nie istnieję, dopóki nie zostanę wykonana.\n";
|
|
}
|
|
}
|
|
|
|
/* Teraz możemy bezpiecznie wywołać foo()
|
|
ponieważ $makefoo ma wartość logiczną 1 */
|
|
|
|
if ($makefoo) foo();
|
|
|
|
function bar()
|
|
{
|
|
echo "Istnieję od początku działania skryptu.\n";
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Funkcje wewnątrz funkcji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo()
|
|
{
|
|
function bar()
|
|
{
|
|
echo "Nie istnieję, dopóki foo() nie jest wywołana.\n";
|
|
}
|
|
}
|
|
|
|
/* Nie możemy tu wywołać bar()
|
|
ponieważ jeszcze nie istnieje. */
|
|
|
|
foo();
|
|
|
|
/* Teraz możemy wywołać bar(),
|
|
wykonanie foo() spodowało
|
|
że jest to już możliwe. */
|
|
|
|
bar();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Wszystkie funkcje i klasy w PHP mają globalny zasięg - mogą być
|
|
wykonane poza funkcją, nawet jeśli były zdefiniowane wewnątrz niej, i odwrotnie.
|
|
</para>
|
|
<simpara>
|
|
PHP nie umożliwia przeładowywania funkcji, nie jest też możliwe
|
|
usunięcie jej definicji lub redefiniowanie poprzednio określonych funkcji.
|
|
</simpara>
|
|
<note>
|
|
<simpara>
|
|
Nazwy funkcji nie rozróżniają wielkości liter dla znaków ASCII od <literal>A</literal> do <literal>Z</literal>, ale dobrym zwyczajem jest
|
|
wywoływanie ich w formie, w której zostały zdefiniowane.
|
|
</simpara>
|
|
</note>
|
|
<simpara>
|
|
Zarówno <link linkend="functions.variable-arg-list">przyjmowanie różnej ilości
|
|
argumentów</link> jak i <link linkend="functions.arguments.default">wartości domyślne
|
|
argumentów</link> są obsługiwane w funkcjach. Zobacz także opisy
|
|
funkcji
|
|
<function>func_num_args</function>,
|
|
<function>func_get_arg</function>, i
|
|
<function>func_get_args</function> aby uzyskać więcej informacji.
|
|
</simpara>
|
|
|
|
<para>
|
|
W PHP jest możliwe wykonywanie rekurencyjnych funkcji.
|
|
<example>
|
|
<title>Funkcje rekurencyjne</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function recursion($a)
|
|
{
|
|
if ($a < 20) {
|
|
echo "$a\n";
|
|
recursion($a + 1);
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<note>
|
|
<simpara>
|
|
Rekurencyjne wywoływanie funkcji/metod z ponad 100-200 poziomami rekurencji
|
|
może spowodować przepełnienie stosu i zakończenie wykonywania skryptu. W
|
|
szczególności nieskończona rekurencja jest uznawana za błąd programistyczny.
|
|
</simpara>
|
|
</note>
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.arguments">
|
|
<title>Argumenty i parametry funkcji</title>
|
|
|
|
<simpara>
|
|
Parametry funkcji są deklarowane w sygnaturze funkcji.
|
|
Dane mogą być przekazywane do funkcji przez listę argumentów,
|
|
która jest listą oddzielonych przecinkami wyrażeń. Argumenty są wykonywane
|
|
od prawej do lewej, a wynik jest przypisywany do parametrów
|
|
funkcji jeszcze przed faktycznym wykonaniem funkcji
|
|
(ang. <literal><emphasis>eager</emphasis> evaluation</literal>).
|
|
</simpara>
|
|
|
|
<para>
|
|
PHP obsługuje podawanie argumentów jako wartości (domyślnie), <link
|
|
linkend="functions.arguments.by-reference">przez
|
|
referencję</link>, oraz <link
|
|
linkend="functions.arguments.default">domyślne wartości
|
|
argumentów</link>. <link linkend="functions.variable-arg-list">zmienna ilość
|
|
argumentów</link> oraz <link linkend="functions.named-arguments">nazwane argumenty</link>
|
|
są także wspierane.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Tablica jako argument funkcji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function takes_array($input)
|
|
{
|
|
echo "$input[0] + $input[1] = ", $input[0]+$input[1];
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Od PHP 8.0.0 lista parametrów funkcji może kończyć się przecinkiem, który zostanie
|
|
zignorowany. Jest to szczególnie przydatne w wypadkach, gdy lista parametrów jest
|
|
długa lub zawiera długie nazwy zmiennych, przez co wygodne byłoby podanie listy parametrów pionowo.
|
|
</para>
|
|
<example>
|
|
<title>Lista parametrów funkcji zakończona przecinkiem</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function przyjmuje_wiele_argumentow(
|
|
$pierwszy_argument,
|
|
$drugi_argument,
|
|
$bardzo_dluga_nazwa_zmiennej_z_argumentem,
|
|
$argument_z_wartoscia_domyslna = 5,
|
|
$znowu = 'domyślny string', // Ten przecinek na końcu nie był dozwolony przed 8.0.0.
|
|
)
|
|
{
|
|
// ...
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<sect2 xml:id="functions.arguments.by-reference">
|
|
<title>Podawanie argumentów jako referencji</title>
|
|
|
|
<simpara>
|
|
Domyślnie, argumenty funkcji podawane są jako wartości (kiedy
|
|
wartość argumentu wewnątrz funkcji się zmienia, nie wpływa
|
|
to na wartość zmiennej poza funkcją). Aby pozwolić funkcji na modyfikację jej
|
|
jej argumentów, muszą one być podane przez referencję.
|
|
</simpara>
|
|
<para>
|
|
Aby argument zawsze był podawany przez referencję, poprzedź nazwę
|
|
parametru znakiem (&) w definicji funkcji:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Podawanie argumentów funkcji przez referencję</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function add_some_extra(&$string)
|
|
{
|
|
$string .= 'i coś ekstra.';
|
|
}
|
|
$str = 'To jest ciąg znaków, ';
|
|
add_some_extra($str);
|
|
echo $str; // wypisuje 'To jest ciąg znaków, i coś ekstra.'
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Przekazywanie wyrażenia stałego jako argument do parametru, który powinien być przekazany przez referencję jest błędem.
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="functions.arguments.default">
|
|
<title>Domyślne wartości parametrów</title>
|
|
|
|
<para>
|
|
Funkcja może zdefiniować domyślne wartości dla parametrów, używając składni podobnej
|
|
do przypisania zmiennej. Domyślna wartość jest używana tylko, gdy argument parametru nie jest
|
|
określony. Należy zauważyć, że przekazanie &null; <emphasis>nie</emphasis>
|
|
ustawia domyślnej wartości.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Użycie domyślnych wartości argumentów w funkcji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makecoffee($type = "cappuccino")
|
|
{
|
|
return "Robię filiżankę $type.\n";
|
|
}
|
|
echo makecoffee();
|
|
echo makecoffee(null);
|
|
echo makecoffee("espresso");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Robię filiżankę cappuccino.
|
|
Robię filiżankę .
|
|
Robię filiżankę espresso.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Domyślne wartości parametrów mogą być wartościami skalarnymi, tablicami (<type>array</type>),
|
|
specjalnym typem &null;, a od PHP 8.1.0 obiektami przy użyciu składni
|
|
<link linkend="language.oop5.basic.new">new ClassName()</link>.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Użycie nie-skalarnych typów jako domyślnych wartości</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makecoffee($types = array("cappuccino"), $coffeeMaker = NULL)
|
|
{
|
|
$device = is_null($coffeeMaker) ? "rąk" : $coffeeMaker;
|
|
return "Robię kubek ".join(", ", $types)." za pomocą $device.\n";
|
|
}
|
|
echo makecoffee();
|
|
echo makecoffee(array("cappuccino", "lavazza"), "czajnika");?>
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Robię kubek cappuccino za pomocą rąk.
|
|
Robię kubek cappuccino, lavazza za pomocą czajnika.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Użycie obiektów jako domyślnych wartości (od PHP 8.1.0)</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class DefaultCoffeeMaker {
|
|
public function brew() {
|
|
return "Robię kawę.\n";
|
|
}
|
|
}
|
|
class FancyCoffeeMaker {
|
|
public function brew() {
|
|
return "Parzę przepyszną kawę specjalnie dla ciebie.\n";
|
|
}
|
|
}
|
|
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
|
|
{
|
|
return $coffeeMaker->brew();
|
|
}
|
|
echo makecoffee();
|
|
echo makecoffee(new FancyCoffeeMaker);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Robię kawę.
|
|
Parzę przepyszną kawę specjalnie dla ciebie.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<simpara>
|
|
Domyślna wartość musi być wyrażeniem stałym, a nie np.
|
|
zmienną, właściwością klasy czy wywołaniem funkcji.
|
|
</simpara>
|
|
<para>
|
|
Zauważ że parametry opcjonalne powinny być zdefiniowane po
|
|
parametrach wymaganych, w przeciwnym razie nie będzie można ich pominąć przy wywołaniu funkcji.
|
|
Spójrz na poniższy przykład:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Niepoprawne użycie domyślnych parametrów funkcji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function jogurt($pojemnik = "kubek", $smak)
|
|
{
|
|
return "Robię $container jogurtu o smaku $flavour.\n";
|
|
}
|
|
|
|
echo makeyogurt("truskawek"); // "truskawek" to $pojemnik, a nie $smak
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Fatal error: Uncaught ArgumentCountError: Too few arguments
|
|
to function jogurt(), 1 passed in example.php on line 42
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
A teraz porównaj to z tym przykładem:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Poprawne użycie domyślnych parametrów funkcji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function jogurt($smak, $pojemnik = "kubek")
|
|
{
|
|
return "Robię $container jogurtu o smaku $flavour.\n";
|
|
}
|
|
|
|
echo makeyogurt("truskawek"); // "truskawek" to $smak
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Robię kubek jogurtu o smaku truskawek.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Od PHP 8.0.0 można użyć <link linkend="functions.named-arguments">nazwanych argumentów</link>
|
|
aby pominąć opcjonalne argumenty.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Poprawne użycie domyślnych parametrów funkcji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function jogurt($smak = "truskawek", $pojemnik = "kubek", $typu = "greckiego")
|
|
{
|
|
return "Robię $container jogurtu $typu o smaku $flavour.\n";
|
|
}
|
|
|
|
echo makeyogurt(style: "natural");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Robię kubek jogurtu naturalnego o smaku truskawek.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Począwszy od PHP 8.0.0, deklarowanie parametrów wymaganych po opcjonalnych
|
|
jest <emphasis>zdeprecjonowane</emphasis>. Zazwyczaj można rozwiązać ten problem
|
|
przez usunięcie domyślnej wartości, ponieważ i tak nie byłaby ona nigdy użyta.
|
|
Wyjątkiem od tej reguły są parametry w postaci
|
|
<code>Typ $parametr = null</code>, gdzie domyślna wartość &null; czyni typ niejawnie
|
|
pozwalającym na null. Taki zapis jest przestarzały od PHP 8.4.0 i powinien być użyty
|
|
wprost <link linkend="language.types.declarations.nullable">typ pozwalający na null</link>.
|
|
<example>
|
|
<title>Deklarowanie parametrów opcjonalnych po wymaganych</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
function foo($a = [], $b) {} // Domyślna wartość nieużywana; zdeprecjonowane od PHP 8.0.0
|
|
function foo($a, $b) {} // Zachowuje się identycznie, brak ostrzeżenia o przestarzałym zapisie
|
|
|
|
function bar(A $a = null, $b) {} // Od PHP 8.1.0, parametr $a jest niejawnie wymagany
|
|
// (gdyż został zdeklarowany przed wymaganym parametrem),
|
|
// ale też niejawnie dopuszcza null (przestarzałe od PHP 8.4.0),
|
|
// ponieważ jego domyślną wartością jest null
|
|
function bar(?A $a, $b) {} // Zalecane
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Od PHP 7.1.0 pominięcie parametru, który nie ma domyślnej wartości,
|
|
rzuca <classname>ArgumentCountError</classname>; w poprzednich wersjach
|
|
powodowało błąd typu <constant>E_WARNING</constant>.
|
|
</simpara>
|
|
</note>
|
|
<note>
|
|
<simpara>
|
|
Parametry przekazywane przez referencję mogą mieć wartość domyślną.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="functions.variable-arg-list">
|
|
<title>Podawanie zmiennej ilości argumentów</title>
|
|
|
|
<simpara>
|
|
PHP wspiera użycie różnej ilości argumentów dla
|
|
funkcji definiowanych przez użytkownika. Jest to możliwe dzięki użyciu
|
|
tokena <literal>...</literal>
|
|
</simpara>
|
|
|
|
<para>
|
|
Lista parametrów może zawierać token
|
|
<literal>...</literal>, który oznacza, że funkcja akceptuje
|
|
zmienną ilość argumentów. Argumenty zostaną przekazane do
|
|
do podanej zmiennej jako tablica, na przykład:
|
|
|
|
<example>
|
|
<title>Użycie <literal>...</literal> do zmiennej ilości argumentów</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function suma(...$liczby) {
|
|
$wynik = 0;
|
|
foreach ($liczby as $liczba) {
|
|
$wynik += $liczba;
|
|
}
|
|
return $wynik;
|
|
}
|
|
|
|
echo suma(1, 2, 3, 4);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
10
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
<literal>...</literal> może być też użyte podczas wywoływania funkcji, aby rozpakować
|
|
tablicę (<type>array</type>) lub <classname>Traversable</classname>, albo literal
|
|
do listy argumentów:
|
|
|
|
<example>
|
|
<title>Użycie <literal>...</literal> do dostarczenia argumentów</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function dodaj($a, $b) {
|
|
return $a + $b;
|
|
}
|
|
|
|
echo dodaj(...[1, 2])."\n";
|
|
|
|
$a = [1, 2];
|
|
echo dodaj(...$a);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
3
|
|
3
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
Możesz określić normalne parametry pozycyjne przed tokenem
|
|
<literal>...</literal>. W tym wypadku tylko końcowe argumenty,
|
|
które nie pasują do żadnego argumentu pozycyjnego, zostaną dodane do tablicy
|
|
generowanej przez <literal>...</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
Jest także możliwe dodanie
|
|
<link linkend="language.types.declarations">określenia typu</link> przez tokenem
|
|
<literal>...</literal>. Jeżeli typ jest obecny, to wszystkie argumenty
|
|
pokrywane przez <literal>...</literal> muszą być obiektami wskazanej klasy.
|
|
|
|
<example>
|
|
<title>Różna ilość argumentów z określeniem typu</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function total_intervals($unit, DateInterval ...$intervals) {
|
|
$time = 0;
|
|
foreach ($intervals as $interval) {
|
|
$time += $interval->$unit;
|
|
}
|
|
return $time;
|
|
}
|
|
|
|
$a = new DateInterval('P1D');
|
|
$b = new DateInterval('P2D');
|
|
echo total_intervals('d', $a, $b).' dni';
|
|
|
|
// Jest to błędem, ponieważ null nie jest obiektem klasy DateInterval.
|
|
echo total_intervals('d', null);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
3 dni
|
|
Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
W końcu, możesz podać także różną ilość argumentów
|
|
<link linkend="functions.arguments.by-reference">przez referencję</link>
|
|
poprzedzając <literal>...</literal> znakiem ampersand
|
|
(<literal>&</literal>).
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 xml:id="functions.named-arguments">
|
|
<title>Nazwane argumenty</title>
|
|
|
|
<para>
|
|
PHP 8.0.0 dodało wsparcie dla nazwanych argumentów jako rozszerzenie istniejących
|
|
argumentów pozycyjnych. Nazwane argumenty pozwalają przekazanie argumentów do
|
|
funkcji na podstawie nazwy parametru, a nie jego pozycji.
|
|
To sprawia, że znaczenie argumentu jest samodokumentujące się, sprawia, że
|
|
argumenty są niezależne od ich kolejności i pozwala na pomijanie dowolnych domyślnych wartości.
|
|
</para>
|
|
|
|
<para>
|
|
Nazwane argumenty są przekazywane przez poprzedzenie wartości nazwą parametru
|
|
zakończoną dwukropkiem. Użycie słów zastrzeżonych jako nazw parametrów jest dozwolone.
|
|
Nazwa parametru musi być identyfikatorem, tworzenie jej dynamicznie
|
|
nie jest dozwolone.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Składnia nazwanych argumentów</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
funkcja(nazwaArgumentu: $wartosc);
|
|
array_foobar(array: $wartosc);
|
|
|
|
// NIE wspierane
|
|
function_name($zmiennaPrzechowujacaNazweArgumentu: $wartosc);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Argumenty pozycyjne vs. argumenty nazwane</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Z użyciem argumentów pozycyjnych:
|
|
array_fill(0, 100, 50);
|
|
|
|
// Z użyciem nazwanych argumentów:
|
|
array_fill(start_index: 0, count: 100, value: 50);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Kolejność, w której są przekazywane nazwane argumenty nie ma znaczenia.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Ten sam przykład co wyżej, z inną kolejnością argumentów</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
array_fill(value: 50, count: 100, start_index: 0);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Nazwane argumenty mogą być używane razem z argumentami pozycyjnymi. W tym wypadku
|
|
nazwane argumenty muszą być podane po argumentach pozycyjnych.
|
|
Jest też możliwe żeby określić tylko część opcjonalnych argumentów
|
|
funkcji, niezależnie od ich kolejności.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Łączenie nazwanych argumentów z argumentami pozycyjnymi</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
htmlspecialchars($string, double_encode: false);
|
|
// To samo co
|
|
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Przekazanie argumentu do tego samego nazwanego parametru wiele razy skutkuje
|
|
wyjątkiem klasy <classname>Error</classname>.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Błąd przy przekazaniu argumentu do tego samego nazwanego parametru wiele razy</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
function foo($parametr) { ... }
|
|
|
|
foo(parametr: 1, parametr: 2);
|
|
// Error: Named parameter $parametr overwrites previous argument
|
|
|
|
foo(1, parametr: 2);
|
|
// Error: Named parameter $parametr overwrites previous argument
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
Od PHP 8.1.0 jest możliwe użycie nazwanych argumentów po rozpakowaniu argumentów.
|
|
Nazwany argument <emphasis>nie może</emphasis> odpisywać już rozpakowanego argumentu.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Użycie nazwanych argumentów po rozpakowaniu</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo($a, $b, $c = 3, $d = 4) {
|
|
return $a + $b + $c + $d;
|
|
}
|
|
|
|
var_dump(foo(...[1, 2], d: 40)); // 46
|
|
var_dump(foo(...['b' => 2, 'a' => 1], d: 40)); // 46
|
|
|
|
var_dump(foo(...[1, 2], b: 20)); // Fatal error. Named parameter $b overwrites previous argument
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.returning-values">
|
|
<title>Zwracanie wartości</title>
|
|
|
|
<para>
|
|
Wartości zwracane są przy użyciu opcjonalnego wyrażenia return. Wszystkie
|
|
typy mogą być zwracane, łącznie z tablicami i obiektami. Powoduje to natychmiastowe
|
|
zakończenie wykonywania funkcji i wznowienie wykonywania skryptu od linijki w której
|
|
funkcja została wywołana. Zobacz <function>return</function>
|
|
aby uzyskać więcej informacji.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Jeżeli <function>return</function> zostanie pominięte, zwrócona będzie
|
|
wartość &null;,
|
|
</para>
|
|
</note>
|
|
|
|
<sect2>
|
|
<title>Użycie return</title>
|
|
<para>
|
|
<example>
|
|
<title>Użycie <function>return</function></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function kwadrat($liczba)
|
|
{
|
|
return $liczba * $liczba;
|
|
}
|
|
echo kwadrat(4); // wypisuje '16'.
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
Funkcja nie może zwracać wielu wartości, ale podobny efekt
|
|
może zostać osiągnięty poprzez zwracanie tablicy.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Zwracanie tablicy</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function small_numbers()
|
|
{
|
|
return array (0, 1, 2);
|
|
}
|
|
|
|
// Destrukturyzacja tablicy przypisze każdy element tablicy do osobnej zmiennej
|
|
[$zero, $one, $two] = small_numbers();
|
|
|
|
// Przed PHP 7.1.0, jedyną alternatywą było użycie konstrukcji list()
|
|
list ($zero, $one, $two) = small_numbers();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Aby zwrócić referencję, użyj operatora & zarówno
|
|
w deklaracji funkcji, jak i podczas przypisywania zwracanej wartości
|
|
zmiennej:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Zwracanie referencji</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function &returns_reference()
|
|
{
|
|
return $someref;
|
|
}
|
|
|
|
$newref =& returns_reference();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Aby uzyskać więcej informacji o referencjach, przejdź do <link
|
|
linkend="language.references">Wyjaśnienie Referencji</link>.
|
|
</simpara>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.variable-functions">
|
|
<title>Funkcje zmiennych</title>
|
|
|
|
<para>
|
|
PHP obsługuje opcję funkcji zmiennych. Oznacza to, że jeśli
|
|
do nazwy zmiennej dodane są nawiasy, PHP postara się znaleźć
|
|
funkcję o nazwie takiej jak wartość zmiennej
|
|
i spróbuje ją wykonać. Między innymi, może to służyć do
|
|
zaimplementowania tzw. callbacks, tablic funkcji, a także wielu innych rzeczy.
|
|
</para>
|
|
<para>
|
|
Funkcje zmiennych nie zadziałają z takimi elementami języka
|
|
jak <function>echo</function>, <function>print</function>,
|
|
<function>unset</function>, <function>isset</function>,
|
|
<function>empty</function>, <function>include</function>,
|
|
<function>require</function> i podobnymi. Używaj okrężnych funkcji
|
|
aby skorzystać z któregoś z powyższych elementów języka jako funkcji zmiennych.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Przykład funkcji zmiennych</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo() {
|
|
echo "W foo()<br />\n";
|
|
}
|
|
|
|
function bar($arg = '')
|
|
{
|
|
echo "W bar(); argumentem było '$arg'.<br />\n";
|
|
}
|
|
|
|
// To jest funkcja okrężna dla "echo"
|
|
function echoit($string)
|
|
{
|
|
echo $string;
|
|
}
|
|
|
|
$func = 'foo';
|
|
$func(); // Wywołuje foo()
|
|
|
|
$func = 'bar';
|
|
$func('test'); // Wywołuje bar()
|
|
|
|
$func = 'echoit';
|
|
$func('test'); // Wywołuje echoit()
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Jako funkcje zmiennych mogą być także wywoływane metody obiektów.
|
|
<example>
|
|
<title>Przykład metod zmiennych</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
function Zmienna()
|
|
{
|
|
$name = 'Bar';
|
|
$this->$name(); // Wywołuje metodę Bar()
|
|
}
|
|
|
|
function Bar()
|
|
{
|
|
echo "To jest Bar";
|
|
}
|
|
}
|
|
|
|
$foo = new Foo();
|
|
$funcname = "Zmienna";
|
|
$foo->$funcname(); // Wywołuje $foo->Zmienna()
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Gdy wywołuje się metody statyczne, wywołanie funkcji jest mocniejsze niż operator właściwości statycznej:
|
|
<example>
|
|
<title>Przykład zmiennej metody z właściwościami statycznymi</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
static $zmienna = 'właściwość statyczna';
|
|
static function Zmienna()
|
|
{
|
|
echo 'Wywołano metodę Zmienna';
|
|
}
|
|
}
|
|
|
|
echo Foo::$zmienna; // Wyświetli 'właściwość statyczna'. Potrzebna jest $zmienna w tym zasięgu.
|
|
$zmienna = "Zmienna";
|
|
Foo::$variable(); // Wywoła $foo->Zmienna() odczytując $zmienna w tym zasięgu.
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Kompleksowy przykład callables</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
static function bar()
|
|
{
|
|
echo "bar\n";
|
|
}
|
|
function baz()
|
|
{
|
|
echo "baz\n";
|
|
}
|
|
}
|
|
|
|
$func = array("Foo", "bar");
|
|
$func(); // wyświetli "bar"
|
|
$func = array(new Foo, "baz");
|
|
$func(); // wyświetli "baz"
|
|
$func = "Foo::bar";
|
|
$func(); // wyświetli "bar"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<sect2 role="seealso">
|
|
&reftitle.seealso;
|
|
<para>
|
|
<simplelist>
|
|
<member><function>is_callable</function></member>
|
|
<member><function>call_user_func</function></member>
|
|
<member><function>function_exists</function></member>
|
|
<member><link linkend="language.variables.variable">zmienne zmiennych</link></member>
|
|
</simplelist>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.internal">
|
|
<title>Wewnętrzne (wbudowane) funkcje</title>
|
|
|
|
<para>
|
|
PHP zapewnia wiele wbudowanych funkcji i konstrukcji. Istnieją także
|
|
funkcje wymagające wkompilowania specyficznych rozszerzeń PHP, w przeciwnym wypadku
|
|
wywołanie ich skutkuje błędami "undefined function". Na przykładd, aby użyć funkcji
|
|
<link linkend="ref.image">obrazków</link> takich jak
|
|
<function>imagecreatetruecolor</function>, PHP musi być skompilowane z obsługą
|
|
<productname>GD</productname>. Aby użyć
|
|
<function>mysqli_connect</function>, PHP musi być skompilowane z obsługą
|
|
<link linkend="book.mysqli">MySQLi</link>. Jest wiele funkcji wbudowanych
|
|
w rdzeń każdej wersji PHP, takich jak funkcje
|
|
<link linkend="ref.strings">typu string</link> oraz
|
|
<link linkend="ref.var">zmiennych</link>. Wywołanie
|
|
to <function>phpinfo</function> lub
|
|
<function>get_loaded_extensions</function> pokaże, które rozszerzenia
|
|
PHP są załadowane. Zauważ, że wiele rozszerzeń jest domyślnie załadowanych i
|
|
podręcznik PHP jest podzielony według rozszerzeń. Zobacz rozdziały o
|
|
<link linkend="configuration">konfiguracji</link>,
|
|
<link linkend="install">instalacji</link>, a także te dotyczące
|
|
poszczególnych rozszerzeń, aby dowiedzieć się jak uruchomić PHP.
|
|
</para>
|
|
<para>
|
|
Czytanie i rozumienie prototypów funkcji wyjaśnione jest w rozdziale
|
|
podręcznika zatytułowanym <link linkend="about.prototypes">jak czytać
|
|
definicje funkcji</link>. Ważne jest zrozumienie, czy funkcja zwraca konkretną wartość
|
|
czy operuje bezpośrednio na podanej zmiennej. Na przykład,
|
|
<function>str_replace</function> zwróci zmodyfikowany obiekt typu string, podczas gdy
|
|
<function>usort</function> pracuje bezpośrednio na podanej zmiennej.
|
|
Każda funkcja posiada swoją stronę w podręczniku PHP, która podaje informacje takie jak
|
|
parametry funkcji, jej zachowanie, wartości zwracane po poprawnym wykonaniu i w przypadku błędu,
|
|
a także dane dotyczące jej dostępności.
|
|
Znanie tych ważnych (chociaż często drobnych) różnic jest kluczowe podczas
|
|
pisania kodu w PHP.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Jeśli parametry podane funkcji nie są takie, jak spodziewane, na przykład
|
|
tablica(<type>array</type>) podawana jest w miejscu, gdzie oczekiwana jest zmienna typu <type>string</type>,
|
|
wartość zwracana przez funkcję nie jest zdefiniowana. W takim wypadku funkcja prawdopodobnie
|
|
zwróci &null; ale jest to jedynie konwencja,
|
|
a nie zasada, na której można się opierać.
|
|
Od PHP 8.0.0 w tej sytuacji będzie rzucony wyjątek <classname>TypeError</classname>.
|
|
</simpara>
|
|
</note>
|
|
<note>
|
|
<para>
|
|
Dla wbudowanych w PHP funkcji typy skalarne domyślnie akceptują null (poza strict mode).
|
|
Od PHP 8.1.0 przekazanie &null; do wbudowanej funkcji, który nie akceptuje wartości null,
|
|
jest niezalecane i emituje komunikat <constant>E_DEPRECATED</constant> w trybie nie-ścisłym, tak aby uzyskać spójne zachowaine z funkcjami deklarowanymi przez użytkownika,
|
|
gdzie typy skalarne muszą być wprost oznaczone jako takie, które akceptują wartość null.
|
|
</para>
|
|
|
|
<para>
|
|
Przykładowo, <function>strlen</function> oczekuje parametru <literal>$string</literal>,
|
|
który będzie typem &string; i nie będzie nullem.
|
|
Ze względów historycznych PHP pozwala na przekazanie &null; jako wartości tego parametru (poza trybem ścisłym) i parametr taki
|
|
jest niejawnie rzutowany na typ <type>string</type>, co skutkuje w przekazaniu wartości <literal>""</literal> do funkcji.
|
|
W trybie ścisłym (strict mode) rzucany jest <classname>TypeError</classname>.
|
|
</para>
|
|
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
var_dump(strlen(null));
|
|
// "Deprecated: Passing null to parameter #1 ($string) of type string is deprecated" as of PHP 8.1.0
|
|
// int(0)
|
|
|
|
var_dump(str_contains("foobar", null));
|
|
// "Deprecated: Passing null to parameter #2 ($needle) of type string is deprecated" as of PHP 8.1.0
|
|
// bool(true)
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</note>
|
|
|
|
<sect2 role="seealso">
|
|
&reftitle.seealso;
|
|
<para>
|
|
<simplelist>
|
|
<member><function>function_exists</function></member>
|
|
<member><link linkend="funcref">listę funkcji</link></member>
|
|
<member><function>get_extension_funcs</function></member>
|
|
<member><function>dl</function></member>
|
|
</simplelist>
|
|
</para>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.anonymous">
|
|
<title>Funkcje anonimowe</title>
|
|
|
|
<simpara>
|
|
Funkcje anonimowe, znane także jako <literal>closures</literal> (pol. domknięcia), pozwalają
|
|
na utworzenie funkcji, które nie mają określonej nazwy. Są najbardziej użyteczne jako
|
|
wartość parametrów typu <type>callable</type>,
|
|
ale mają też wiele innych zastosowań.
|
|
</simpara>
|
|
<simpara>
|
|
Funkcje anonimowe są zaimplementowane przy użyciu klasy <link linkend="class.closure">Closure</link>.
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Przykład funkcji anonimowej</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo preg_replace_callback('~-([a-z])~', function ($match) {
|
|
return strtoupper($match[1]);
|
|
}, 'hello-world');
|
|
// wyświetli helloWorld
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<simpara>
|
|
Domknięcia mogą zostać użyte także jako wartości zmiennych; PHP automatycznie
|
|
konwertuje takie wyrażenia na instancje
|
|
wewnętrznej klasy <classname>Closure</classname>. Przypisanie domknięcia do
|
|
zmiennej korzysta z takiej samej składni jak każde inne przypisanie, włączając w to
|
|
średnik na końcu:
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Przypisanie funkcji anonimowej do zmiennej</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$greet = function($name) {
|
|
printf("Witaj %s\r\n", $name);
|
|
};
|
|
|
|
$greet('Świecie');
|
|
$greet('PHP');
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<simpara>
|
|
Domknięcia mogą także dziedziczyć zmienne z zasięgu nadrzędnego. Każda taka
|
|
musi być przekazana za pomocą kontrukcji <literal>use</literal>.
|
|
Od PHP 7.1 jako takie zmienne nie mogą zostać użyte &link.superglobals;,
|
|
<varname>$this</varname> oraz zmienne o nazwach takich jak parametry.
|
|
Deklaracja zwracanego typu musi zostać umieszczona <emphasis>po</emphasis>
|
|
słowie kluczowym <literal>use</literal>.
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Dziedziczenie zmiennych z nadrzędnego zakresu</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$message = 'hello';
|
|
|
|
// Brak "use"
|
|
$example = function () {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// Odziedzicz $message
|
|
$example = function () use ($message) {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// Wartość jest dziedziczona podczas definiowania funkcji,
|
|
// a nie jej wykonywania
|
|
$message = 'world';
|
|
$example();
|
|
|
|
// Zresetuj wiadomosć
|
|
$message = 'hello';
|
|
|
|
// Odziedzicz przez referencje
|
|
$example = function () use (&$message) {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// Zmieniona wartość w zasięgu nadrzędnym jest
|
|
// brana pod uwagę wewnątrz wywołania funkcji
|
|
$message = 'world';
|
|
$example();
|
|
|
|
// Domknięcia mogą także przyjmować normalne argumenty
|
|
$example = function ($arg) use ($message) {
|
|
var_dump($arg . ' ' . $message);
|
|
};
|
|
$example("hello");
|
|
|
|
// Deklaracja zwracanego typu jest umieszczona po słowie kluczowym use
|
|
$example = function () use ($message): string {
|
|
return "hello $message";
|
|
};
|
|
var_dump($example());
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
Notice: Undefined variable: message in /example.php on line 6
|
|
NULL
|
|
string(5) "hello"
|
|
string(5) "hello"
|
|
string(5) "hello"
|
|
string(5) "world"
|
|
string(11) "hello world"
|
|
string(11) "hello world"
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
Od PHP 8.0.0, lista argumentów przekazanych do konstrukcji <literal>list</literal> może kończyć się
|
|
przecinkiem, który zostanie zignorowany.
|
|
</para>
|
|
<simpara>
|
|
Dziedziczenie zmiennych z zasięgu nadrzędnego to <emphasis>nie</emphasis>
|
|
to samo co użycie zmiennych globalnych.
|
|
Zmienne globalne istnieją w zasięgu globalnym, który jest jednakowy
|
|
bez względu na wykonywaną funkcję. Nadrzędnym zasięgiem domknięcia jest
|
|
funkcja, w której domknięcie zostało zadeklarowane (niekoniecznie funkcja,
|
|
z której zostało wykonane). Zobacz poniższy przykład:
|
|
</simpara>
|
|
|
|
<example>
|
|
<title>Domknięcia i zasięg</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Podstawowy koszyk sklepowy, który zawiera listę dodanych produktów
|
|
// i ilość każdego z nich. Zawiera metodę, która
|
|
// liczy całkowitą cenę produktów w koszyku używając
|
|
// funkcji anonimowej jako callbacku.
|
|
class Cart
|
|
{
|
|
const PRICE_BUTTER = 1.00;
|
|
const PRICE_MILK = 3.00;
|
|
const PRICE_EGGS = 6.95;
|
|
|
|
protected $products = array();
|
|
|
|
public function add($product, $quantity)
|
|
{
|
|
$this->products[$product] = $quantity;
|
|
}
|
|
|
|
public function getQuantity($product)
|
|
{
|
|
return isset($this->products[$product]) ? $this->products[$product] :
|
|
FALSE;
|
|
}
|
|
|
|
public function getTotal($tax)
|
|
{
|
|
$total = 0.00;
|
|
|
|
$callback =
|
|
function ($quantity, $product) use ($tax, &$total)
|
|
{
|
|
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
|
|
strtoupper($product));
|
|
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
|
|
};
|
|
|
|
array_walk($this->products, $callback);
|
|
return round($total, 2);
|
|
}
|
|
}
|
|
|
|
$my_cart = new Cart;
|
|
|
|
// Dodaj produkty do koszyka
|
|
$my_cart->add('butter', 1);
|
|
$my_cart->add('milk', 3);
|
|
$my_cart->add('eggs', 6);
|
|
|
|
// Wyświetl całkowitą cenę z 5% podatkiem.
|
|
print $my_cart->getTotal(0.05) . "\n";
|
|
// Wynik to 54.29
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<example>
|
|
<title>Automatyczne przypisanie <literal>$this</literal></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Test
|
|
{
|
|
public function testing()
|
|
{
|
|
return function() {
|
|
var_dump($this);
|
|
};
|
|
}
|
|
}
|
|
|
|
$object = new Test;
|
|
$function = $object->testing();
|
|
$function();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
object(Test)#1 (0) {
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
|
|
<para>
|
|
Gdy funkcja anonimowa jest zadeklarowana w kontekście klasy,
|
|
obecna klasa jest automatycznie do niej przypisywana, sprawiając, że w zakresie
|
|
funkcji jest dostępna zmienna <literal>$this</literal>. Jeśli to automatyczne
|
|
powiązywanie jest niepożądane, można w zamian użyć
|
|
<link linkend="functions.anonymous-functions.static">statycznych funkcji
|
|
anonimowych</link>.
|
|
</para>
|
|
|
|
<sect2 xml:id="functions.anonymous-functions.static">
|
|
<title>Statyczne funkcje anonimowe</title>
|
|
<para>
|
|
Funkcje anonimowe mogą być zadeklarowane jako statyczne.
|
|
Zapobiega to przed automatycznym przypisaniem do nich obecnej klasy.
|
|
Nie można też przypisać do nich obiektów w czasie wykonywania skryptu.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Próba użycia <literal>$this</literal> wewnątrz statycznej funkcji anonimowej</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Foo {
|
|
{
|
|
function __construct()
|
|
{
|
|
$func = static function() {
|
|
var_dump($this);
|
|
};
|
|
$func();
|
|
}
|
|
};
|
|
new Foo();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Notice: Undefined variable: this in %s on line %d
|
|
NULL
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
|
|
<para>
|
|
<example>
|
|
<title>Próba przypisania obiektu do statycznej funkcji anonimowej</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$func = static function() {
|
|
// ciało funkcji
|
|
};
|
|
$func = $func->bindTo(new stdClass);
|
|
$func();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Warning: Cannot bind an instance to a static closure in %s on line %d
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="changelog">
|
|
&reftitle.changelog;
|
|
<para>
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>8.3.0</entry>
|
|
<entry>
|
|
Domknięcia utworzone z <link linkend="language.oop5.magic">metod
|
|
magicznych</link> mogą przyjmować nazwane parametry.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>7.1.0</entry>
|
|
<entry>
|
|
Funkcje anonimowe nie mogą używać &link.superglobals;,
|
|
<varname>$this</varname> oraz zmiennych o nazwach takich
|
|
jak parametry.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="notes">
|
|
&reftitle.notes;
|
|
<note>
|
|
<simpara>
|
|
Wewnątrz funkcji anonimowej można używać <function>func_num_args</function>,
|
|
<function>func_get_arg</function> i <function>func_get_args</function>.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
<sect1 xml:id="functions.arrow">
|
|
<title>Funkcje strzałkowe (arrow functions)</title>
|
|
|
|
<simpara>
|
|
Funkcje strzałkowe zostały wprowadzone w PHP 7.4 jako bardziej zwięzła składnia dla
|
|
<link linkend="functions.anonymous">funkcji anonimowych</link>.
|
|
</simpara>
|
|
<simpara>
|
|
Zarówno funkcje anonimowe jak i strzałkowe są zaimplementowane przy użyciu
|
|
klasy <link linkend="class.closure"><classname>Closure</classname></link>.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
Funkcje strzałkowe mają podstawową składnię
|
|
<code>fn (lista_argumentów) => wyrażenie</code>.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
Funkcje strzałkowe wspierają takie same funkcjonalności jak
|
|
<link linkend="functions.anonymous">funkcje anonimowe</link>,
|
|
z tym że użycie zmiennych z zasięgu rodzica jest zawsze automatyczne.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
Kiedy zmienna użyta w wyrażeniu jest zdefiniowana w zasięgu rodzica,
|
|
będzie automatycznie widoczna (przez wartość, nie przez referencję).
|
|
W następującym przykładzie funkcje <varname>$fn1</varname> i
|
|
<varname>$fn2</varname> działają identycznie.
|
|
</simpara>
|
|
|
|
<para>
|
|
<example>
|
|
<title>Funkcje strzałkowe automatycznie przejmują wartości zmiennych</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$y = 1;
|
|
|
|
$fn1 = fn($x) => $x + $y;
|
|
// odpowiednik użycia $y jak poniżej:
|
|
$fn2 = function ($x) use ($y) {
|
|
return $x + $y;
|
|
};
|
|
|
|
var_export($fn1(3));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
4
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Działa to także gdy funkcje strzałkowe są zagnieżdżone:
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Funkcje strzałkowe automatycznie przejmują wartości zmiennych, nawet gdy zagnieżdżone</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$z = 1;
|
|
$fn = fn($x) => fn($y) => $x * $y + $z;
|
|
// Wyświetla 51
|
|
var_export($fn(5)(10));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Podobnie jak w funkcjach anonimowych
|
|
funkcje strzałkowe pozwalają na dowolną sygnaturę funkcji,
|
|
w tym na typy parametrów, typ zwracanej wartości, wartości domyślne,
|
|
przyjmowanie zmiennej ilości argumentów, a także przyjmowanie i zwracanie
|
|
wartości przez referencję.
|
|
Wszystkie poniższe są prawidłowymi przykładami funkcji strzałkowych:
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Przykłady funkcji strzałkowych</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
fn(array $x) => $x;
|
|
static fn($x): int => $x;
|
|
fn($x = 42) => $x;
|
|
fn(&$x) => $x;
|
|
fn&($x) => $x;
|
|
fn($x, ...$pozostale) => $pozostale;
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Funkcje strzałkowe przekazują wartości zmiennych (a nie referencje do nich).
|
|
Jest to w zasadzie odpowiednikiem użycia <code>use($x)</code> dla każdej
|
|
zmiennej <varname>$x</varname> użytej wewnątrz funkcji strzałkowej.
|
|
Przekazywanie przez wartość oznacza, że nie jest możliwe zmodyfikowanie wartości
|
|
z zewnętrznego zakresu zmiennych.
|
|
W celu przekazania zmiennych przez referencję można skorzystać z
|
|
<link linkend="functions.anonymous">funkcji anonimowych</link>.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Wartości z zewnętrznego zakresu nie mogą być modyfikowane przez funkcje strzałkowe</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$x = 1;
|
|
$fn = fn() => $x++; // Nie ma wpływu na $x
|
|
$fn();
|
|
var_export($x); // Wyświetli 1
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<sect2 role="changelog">
|
|
&reftitle.changelog;
|
|
<para>
|
|
<informaltable>
|
|
<tgroup cols="2">
|
|
<thead>
|
|
<row>
|
|
<entry>&Version;</entry>
|
|
<entry>&Description;</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry>7.4.0</entry>
|
|
<entry>
|
|
Dodano obsługę funkcji strzałkowych.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="notes">
|
|
&reftitle.notes;
|
|
<note>
|
|
<simpara>
|
|
Wewnątrz funkcji strzałkowej można używać <function>func_num_args</function>,
|
|
<function>func_get_arg</function> i <function>func_get_args</function>.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.first_class_callable_syntax">
|
|
<title>Obsługa callable przy użyciu dedykowanej składni (first-class)</title>
|
|
|
|
<para>
|
|
PHP 8.1.0 wprowadziło dedykowaną składnię, aby umożliwić tworzenie <link linkend="functions.anonymous">funkcji anonimowych</link> z typu <link linkend="language.types.callable">callable</link>.
|
|
Ta składnia jest rekomendowana zamiast wcześniejszych składni korzystających z tablic lub specjalnych ciągów znaków.
|
|
Zaletą użycia dedykowanej składni jest jej zrozumiałość dla narzędzi wykonujących analizę statyczną oraz użycie zakresu w momencie tworzenia callable.
|
|
</para>
|
|
|
|
<para>
|
|
Składnia <code>WyrażenieCallable(...)</code> jest używana do stworzenia obiektu <classname>Closure</classname> z callable. <code>WyrażenieCallable</code> może być dowolnym wyrażeniem, które może zostać bezpośrednio wywołane wg gramatyki PHP:
|
|
<example>
|
|
<title>Prosta składnia dedykowana (first-class) dla callable</title>
|
|
<programlisting role="php">
|
|
<;
|
|
$f9 = [Foo::class, 'staticmethod'](...);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Znaki <code>...</code> są częścią składni, a nie pomięciem.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
<code>WyrażenieCallable(...)</code> ma taką samą semantykę jak <methodname>Closure::fromCallable</methodname>.
|
|
To znaczy, w przeciwieństwie do składni callable korzystającej z ciągów znaków lub tablic, <code>WyrażenieCallable(...)</code> bierze pod uwagę zakres widoczności w chwili, gdy jest tworzone:
|
|
<example>
|
|
<title>Porównanie zakresu widoczności dla <code>WyrażenieCallable(...)</code> i tradycyjnej składni callable</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
class Foo {
|
|
public function getPrivateMethod() {
|
|
return [$this, 'privateMethod'];
|
|
}
|
|
|
|
private function privateMethod() {
|
|
echo __METHOD__, "\n";
|
|
}
|
|
}
|
|
|
|
$foo = new Foo;
|
|
$privateMethod = $foo->getPrivateMethod();
|
|
$privateMethod();
|
|
// Fatal error: Call to private method Foo::privateMethod() from global scope
|
|
// Dzieje się tak ponieważ wywołanie odbywa się spoza klasy Foo i modyfikator widoczności metody będzie sprawdzony
|
|
|
|
class Foo1 {
|
|
public function getPrivateMethod() {
|
|
// Używa zakresu widoczności w momencie tworzenia callable.
|
|
return $this->privateMethod(...); // odpowiednik Closure::fromCallable([$this, 'privateMethod']);
|
|
}
|
|
|
|
private function privateMethod() {
|
|
echo __METHOD__, "\n";
|
|
}
|
|
}
|
|
|
|
$foo1 = new Foo1;
|
|
$privateMethod = $foo1->getPrivateMethod();
|
|
$privateMethod(); // Foo1::privateMethod
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Tworzenie obiektów przy użyciu tej składni (np. <code>new Foo(...)</code>) nie jest obsługiwane, ponieważ składnia <code>new Foo()</code> nie jest uznawana za wywołanie.
|
|
</para>
|
|
</note>
|
|
|
|
<note>
|
|
<para>
|
|
Dedykowanej składni do obsługi callable nie można łączyć z <link linkend="language.oop5.basic.nullsafe">operatorem nullsafe</link>. Oba z poniższych zakończą się błędem w trakcie kompilacji skryptu:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$obj?->method(...);
|
|
$obj?->prop->method(...);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</note>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|