OK, zupełnie zapomniałem, jak pomijać argumenty w PHP.
Powiedzmy, że mam:
function getData($name, $limit = '50', $page = '1') {
...
}
Jak nazwałbym tę funkcję, aby środkowy parametr miał wartość domyślną (tj. „50”)?
getData('some name', '', '23');
Czy powyższe byłyby prawidłowe? Nie wydaje mi się, żeby to działało.
php
function
parameters
default-value
optional-parameters
Chuck Le Butt
źródło
źródło
ReflectionFunction
. Opublikowałem tę odpowiedź w podobnym pytaniu.Odpowiedzi:
Twój post jest poprawny.
Niestety, jeśli chcesz użyć opcjonalnego parametru na samym końcu listy parametrów, musisz określić wszystko, aż do ostatniego parametru. Generalnie, jeśli chcesz mieszać i dopasowywać, podajesz im domyślne wartości
''
lubnull
i nie używaj ich wewnątrz funkcji, jeśli mają taką wartość domyślną.źródło
$limit = is_numeric($limit) ? $limit : '50';
na początku getData funkcjiNie ma innego sposobu na „pominięcie” argumentu niż określenie domyślnego, takiego jak
false
lubnull
.Ponieważ w PHP brakuje trochę cukru składniowego, często zobaczysz coś takiego:
checkbox_field(array( 'name' => 'some name', .... ));
Który, jak elokwentnie powiedziano w komentarzach, używa tablic do emulacji nazwanych argumentów.
Daje to najwyższą elastyczność, ale w niektórych przypadkach może nie być potrzebne. Przynajmniej możesz przenieść wszystko, co według ciebie nie jest oczekiwane przez większość czasu na koniec listy argumentów.
źródło
Nie, w ten sposób nie można pominąć argumentów. Możesz pominąć przekazywanie argumentów tylko wtedy, gdy znajdują się one na końcu listy parametrów.
Pojawiła się oficjalna propozycja: https://wiki.php.net/rfc/skipparams , która została odrzucona. Strona propozycji zawiera linki do innych pytań SO na ten temat.
źródło
Nic się nie zmieniło, jeśli chodzi o możliwość pominięcia argumentów opcjonalnych, jednak dla poprawnej składni i możliwości określenia NULL dla argumentów, które chcę pominąć, oto jak bym to zrobił:
define('DEFAULT_DATA_LIMIT', '50'); define('DEFAULT_DATA_PAGE', '1'); /** * getData * get a page of data * * Parameters: * name - (required) the name of data to obtain * limit - (optional) send NULL to get the default limit: 50 * page - (optional) send NULL to get the default page: 1 * Returns: * a page of data as an array */ function getData($name, $limit = NULL, $page = NULL) { $limit = ($limit===NULL) ? DEFAULT_DATA_LIMIT : $limit; $page = ($page===NULL) ? DEFAULT_DATA_PAGE : $page; ... }
Można to wywołać w ten sposób:
getData('some name',NULL,'23');
a każdy wywołujący funkcję w przyszłości nie musi za każdym razem pamiętać wartości domyślnych lub zadeklarowanej dla nich stałej.źródło
Prosta odpowiedź brzmi: nie . Ale po co pomijać, gdy ponowne ułożenie argumentów pozwala to osiągnąć?
Twój to „ Nieprawidłowe użycie domyślnych argumentów funkcji ” i nie będzie działać tak, jak tego oczekujesz.
Dodatkowa uwaga z dokumentacji PHP:
Rozważ następujące:
function getData($name, $limit = '50', $page = '1') { return "Select * FROM books WHERE name = $name AND page = $page limit $limit"; } echo getData('some name', '', '23'); // won't work as expected
Wynik będzie:
"Select * FROM books WHERE name = some name AND page = 23 limit"
Prawidłowe użycie domyślnych argumentów funkcji powinno wyglądać następująco:
function getData($name, $page = '1', $limit = '50') { return "Select * FROM books WHERE name = $name AND page = $page limit $limit"; } echo getData('some name', '23'); // works as expected
Wynik będzie:
"Select * FROM books WHERE name = some name AND page = 23 limit 50"
Umieszczenie wartości domyślnej po prawej stronie po wartościach innych niż domyślne zapewnia, że zawsze przywróci domyślną wartość tej zmiennej, jeśli nie została zdefiniowana / podana. Oto link do odniesienia i skąd pochodzą te przykłady.
Edycja: ustawienie tego,
null
co sugerują inni, może działać i jest inną alternatywą, ale może nie odpowiadać temu, co chcesz. Zawsze ustawi wartość domyślną na null, jeśli nie jest zdefiniowana.źródło
Dla każdego pominiętego parametru (musisz) przejść z parametrem domyślnym, aby być po bezpiecznej stronie.
(Ustalenie wartości null, gdzie domyślnym parametrem jest `` '' lub podobny lub odwrotnie, spowoduje kłopoty ...)
źródło
Jak wspomniano powyżej, nie będzie można pominąć parametrów. Napisałem tę odpowiedź, aby zapewnić dodatek, który był zbyt duży, aby umieścić go w komentarzu.
@Frank Nocke proponuje wywołanie funkcji z jej domyślnymi parametrami, czyli na przykład posiadanie
function a($b=0, $c=NULL, $d=''){ //...
powinieneś użyć
$var = a(0, NULL, 'ddd');
co funkcjonalnie będzie takie samo, jak pominięcie pierwszych dwóch (
$b
i$c
) parametrów.Nie jest jasne, które z nich są wartościami domyślnymi (
0
wpisano, aby zapewnić wartość domyślną, czy jest to ważne?).Istnieje również niebezpieczeństwo, że problem z wartościami domyślnymi jest powiązany z funkcją zewnętrzną (lub wbudowaną), gdy wartości domyślne mogą być zmieniane przez autora funkcji (lub metody). Więc jeśli nie zmieniasz swojego wywołania w programie, możesz nieumyślnie zmienić jego zachowanie.
Pewnym obejściem może być zdefiniowanie pewnych stałych globalnych, na przykład
DEFAULT_A_B
„domyślnej wartości parametru B funkcji A” i parametrów „pomiń” w ten sposób:$var = a(DEFAULT_A_B, DEFAULT_A_C, 'ddd');
W przypadku klas łatwiej i bardziej elegancko jest zdefiniować stałe klasowe, ponieważ są one częścią zasięgu globalnego, np.
class MyObjectClass { const DEFAULT_A_B = 0; function a($b = self::DEFAULT_A_B){ // method body } } $obj = new MyObjectClass(); $var = $obj->a(MyObjectClass::DEFAULT_A_B); //etc.
Zauważ, że ta domyślna stała jest definiowana dokładnie raz w całym kodzie (nie ma wartości nawet w deklaracji metody), więc w przypadku pewnych nieoczekiwanych zmian, zawsze będziesz podawać funkcję / metodę z poprawną wartością domyślną.
Klarowność tego rozwiązania jest oczywiście lepsze niż dostarczanie surowych wartości domyślnych (jak
NULL
,0
itd.), Które nie mówią nic do czytnika.(Zgadzam się, że dzwonienie podoba
$var = a(,,'ddd');
byłoby najlepszą opcją)źródło
Nie możesz pominąć argumentów, ale możesz użyć parametrów tablicowych i musisz zdefiniować tylko 1 parametr, który jest tablicą parametrów.
function myfunction($array_param) { echo $array_param['name']; echo $array_param['age']; ............. }
Możesz dodać tyle parametrów, ile potrzebujesz, nie musisz ich definiować. Kiedy wywołujesz funkcję, umieszczasz parametry w ten sposób:
myfunction(array("name" => "Bob","age" => "18", .........));
źródło
Cóż, jak wszyscy już powiedzieli, że to, czego chcesz, nie będzie możliwe w PHP bez dodania jakichkolwiek linii kodu w funkcji.
Ale możesz umieścić ten fragment kodu na górze funkcji, aby uzyskać swoją funkcjonalność:
foreach((new ReflectionFunction(debug_backtrace()[0]["function"]))->getParameters() as $param) { if(empty(${$param->getName()}) && $param->isOptional()) ${$param->getName()} = $param->getDefaultValue(); }
Więc w zasadzie
debug_backtrace()
otrzymuję nazwę funkcji, w której ten kod jest umieszczony, aby następnie utworzyć nowyReflectionFunction
obiekt i zapętlić wszystkie argumenty funkcji.W pętli po prostu sprawdzam, czy argumentem funkcji jest
empty()
AND argument jest „opcjonalny” (czyli ma wartość domyślną). Jeśli tak, po prostu przypisuję wartość domyślną do argumentu.Demo
źródło
Ustaw limit na null
function getData($name, $limit = null, $page = '1') { ... }
i wywołaj tę funkcję
getData('some name', null, '23');
jeśli chcesz ustawić limit, możesz podać jako argument
getData('some name', 50, '23');
źródło
Zgodnie z wcześniejszymi zaleceniami nic się nie zmieniło. Uważaj jednak, zbyt wiele parametrów (szczególnie opcjonalnych) jest silnym wskaźnikiem zapachu kodu.
Być może Twoja funkcja robi za dużo:
// first build context $dataFetcher->setPage(1); // $dataFetcher->setPageSize(50); // not used here // then do the job $dataFetcher->getData('some name');
Niektóre parametry można pogrupować logicznie:
$pagination = new Pagination(1 /*, 50*/); getData('some name', $pagination); // Java coders will probably be familiar with this form: getData('some name', new Pagination(1));
W ostateczności zawsze możesz wprowadzić parametr ad-hoc :
$param = new GetDataParameter(); $param->setPage(1); // $param->setPageSize(50); // not used here getData($param);
(co jest tylko gloryfikowaną wersją mniej formalnej techniki tablic parametrów )
Czasami sam powód, dla którego parametr jest opcjonalny, jest zły. Czy w tym przykładzie
$page
naprawdę ma być opcjonalne? Czy uratowanie kilku postaci naprawdę robi różnicę?// dubious // it is not obvious at first sight that a parameterless call to "getData()" // returns only one page of data function getData($page = 1); // this makes more sense function log($message, $timestamp = null /* current time by default */);
źródło
Ten fragment:
Odpowiedź to :
źródło
Oto, co bym zrobił:
<?php function getData($name, $limit = '', $page = '1') { $limit = (EMPTY($limit)) ? 50 : $limit; $output = "name=$name&limit=$limit&page=$page"; return $output; } echo getData('table'); /* output name=table&limit=50&page=1 */ echo getData('table',20); /* name=table&limit=20&page=1 */ echo getData('table','',5); /* output name=table&limit=50&page=5 */ function getData2($name, $limit = NULL, $page = '1') { $limit = (ISSET($limit)) ? $limit : 50; $output = "name=$name&limit=$limit&page=$page"; return $output; } echo getData2('table'); // /* output name=table&limit=50&page=1 */ echo getData2('table',20); /* output name=table&limit=20&page=1 */ echo getData2('table',NULL,3); /* output name=table&limit=50&page=3 */ ?>
Mam nadzieję, że to komuś pomoże
źródło
To trochę stare pytanie z wieloma technicznie kompetentnymi odpowiedziami, ale woła o jeden z nowoczesnych wzorców projektowych w PHP: Programowanie zorientowane obiektowo. Zamiast wstrzykiwać zbiór prymitywnych skalarnych typów danych, rozważ użycie „wstrzykniętego obiektu”, który zawiera wszystkie dane wymagane przez funkcję. http://php.net/manual/en/language.types.intro.php
Wstrzyknięty obiekt może mieć procedury walidacji właściwości itp. Jeśli tworzenie instancji i wstrzyknięcie danych do wstrzykniętego obiektu nie jest w stanie przejść całej weryfikacji, kod może natychmiast zgłosić wyjątek, a aplikacja może uniknąć niezręcznego procesu z potencjalnie niekompletnymi danymi.
Możemy podpowiedzieć wpisany obiekt, aby wychwycić błędy przed wdrożeniem. Niektóre pomysły zostały podsumowane w tym artykule sprzed kilku lat.
https://www.experts-exchange.com/articles/18409/Using-Named-Parameters-in-PHP-Function-Calls.html
źródło
Musiałem stworzyć Factory z opcjonalnymi parametrami, moim obejściem było użycie operatora koalescencji zerowej:
public static function make( string $first_name = null, string $last_name = null, string $email = null, string $subject = null, string $message = null ) { $first_name = $first_name ?? 'First'; $last_name = $last_name ?? 'Last'; $email = $email ?? '[email protected]'; $subject = $subject ?? 'Some subject'; $message = $message ?? 'Some message'; }
Stosowanie:
$factory1 = Factory::make('First Name Override'); $factory2 = Factory::make(null, 'Last Name Override'); $factory3 = Factory::make(null, null, null, null 'Message Override');
Nie jest to najpiękniejsza rzecz, ale może być dobrym wzorem do wykorzystania w fabrykach do testów.
źródło
Spróbuj tego.
function getData($name, $limit = NULL, $page = '1') { if (!$limit){ $limit = 50; } } getData('some name', '', '23');
źródło
Nie możesz pominąć środkowego parametru w wywołaniu funkcji. Ale możesz obejść to:
function_call('1', '2', '3'); // Pass with parameter. function_call('1', null, '3'); // Pass without parameter.
Funkcjonować:
function function_call($a, $b='50', $c){ if(isset($b)){ echo $b; } else{ echo '50'; } }
źródło
Jak zauważył @IbrahimLawal. Najlepszą praktyką jest po prostu ustawienie
null
wartości. Po prostu sprawdź, czy przekazana wartość jest wartością,null
w której używasz zdefiniowanych wartości domyślnych.<?php define('DEFAULT_LIMIT', 50); define('DEFAULT_PAGE', 1); function getData($name, $limit = null, $page = null) { $limit = is_null($limit) ? DEFAULT_LIMIT : $limit; $page = is_null($page) ? DEFAULT_PAGE : $page; ... } ?>
Mam nadzieję że to pomoże.
źródło
getData('some name');
po prostu ich nie przekazuj, a domyślna wartość zostanie zaakceptowana
źródło