PHP'de kapanış nedir ve neden bir kullanım tanımlayıcısı kullanıyor?

PHP 5.3.0 bazı özelliklerine bakıyorum ve oldukça komik görünen bir sitedeki bazı kodlara bakıyorum:

 public function getTotal($tax) { $total = 0.00; $callback =  function ($quantity, $product) use ($tax,  { $pricePerItem = constant(__CLASS__ . "::PRICE_" . strtoupper($product)); $total += ($pricePerItem * $quantity) * ($tax + 1.0); }; array_walk($this->products, $callback); return round($total, 2); } 

anonim işlevlerin bir örneği olarak.

Bunu bilen var mı? Herhangi bir belge var mı? Ve eğer kullanırsan kötü görünüyor mu?

346
30 июня '09 в 21:21 2009-06-30 21:21 SeanDowney , 30 Haziran 099’da 21:21, 2009-06-30 21:21
@ 6 cevaplar

Böylece PHP kapanmayı ifade eder. Bu hiç de kötü değil, ama aslında oldukça güçlü ve kullanışlıdır.

Temel olarak, bu, anonim bir işlevin, yerel değişkenleri (bu durumda, $tax ve $tax bir referans) kapsam dışında "yakalamasına" izin verir ve değerlerini (veya $total olması durumunda, $total referans) bir durum olarak saklar. en anonim işlev içinde.

305
30 июня '09 в 21:24 2009-06-30 21:24 Cevap Andrew Hare tarafından 30 Haziran '09' da 21:24 2009-06-30 21:24 tarihinde verilmiştir.

Basit cevap

function ($quantity) use ($tax, { .. };

border=0
  • Kapatma, bir değişkene atanmış bir fonksiyondur, böylece onu geçebilirsiniz
  • Kapatma ayrı bir ad alanıdır, genellikle bu ad alanının dışında tanımlanan değişkenlere erişemezsiniz. Use anahtar sözcüğü geliyor:
  • use , aşağıdaki değişkenleri kapat içinde kullanmanıza (kullanmanıza) olanak sağlar.
  • kullanım - erken bağlama. Bu, COPIED değişkenlerinin değerlerinin kapatma belirlendiğinde ayarlandığı anlamına gelir. Bu nedenle, devre içindeki $tax değerini değiştirmek, nesne olarak bir işaretçi olmadığı sürece dış etkiye sahip değildir.
  • Değişkenleri işaretçiler olarak, örneğin > olması durumunda geçirebilirsiniz. Bu nedenle, $total değerini değiştirmek dış etkiye neden olur, değişkenin baş>
  • Kapaklar içinde tanımlanan değişkenler de kapaklar nedeniyle kullanılamaz.
  • Kapaklar ve fonksiyonlar aynı hızdadır. Evet, onları bütün senaryolarınızda kullanabilirsiniz.

@ Mytskine'ın belirttiği gibi, en iyi açıklama kapanışlar için RFC'dir. (Bunun için yukarı kaldırın.)

404
24 апр. cevabı 24 nisan zupa verilir . 2012-04-24 21:39 '12, 09:39, 2012-04-24 21:39

kapanışlar harika! anonim işlevlerle ilgili birçok sorunu çözerler ve gerçekten zarif bir kodu mümkün kılarlar (en azından php hakkında konuşurken).

Javascript programcıları, bazen değişkenleri açıkça tanımlanmadığı için php'de kullanılanlar nedeniyle, bazen onu bile bile bilmeden kapamaları kullanırlar.

Gerçek dünyaya yukarıda verilenlerden daha iyi örnekler var. Diyelim ki çok boyutlu bir diziyi alt-değere göre sıralamanız gerekiyor, fakat anahtar değişiyor.

 <?php function generateComparisonFunctionForKey($key) { return function ($left, $right) use ($key) { if ($left[$key] == $right[$key]) return 0; else return ($left[$key] < $right[$key]) ? -1 : 1; }; } $myArray = array( array('name' => 'Alex', 'age' => 70), array('name' => 'Enrico', 'age' => 25) ); $sortByName = generateComparisonFunctionForKey('name'); $sortByAge = generateComparisonFunctionForKey('age'); usort($myArray, $sortByName); usort($myArray, $sortByAge); ?> 

uyarı: denetlenmeyen kod (php5.3 atm yüklü değil), ancak böyle bir şey görünmesi gerekir.

Bir dezavantajı var: bir kapatma ile gelirseniz birçok php geliştiricisi biraz çaresiz olabilir.

daha fazla anlamak için, daha fazla kapanış, size başka bir örnek vereceğim - bu sefer javascript'te. Sorunlardan biri de asenkron kapsama alanı ve tarayıcıya özgüdür. özellikle window.setTimeout(); gelince window.setTimeout(); (veya - interval). bu nedenle, setTimeout işlevini geçersiniz, ancak parametre oluşturma kodu çalıştırdığı için hiçbir parametre veremezsiniz!

 function getFunctionTextInASecond(value) { return function () { document.getElementsByName('body')[0].innerHTML = value; // "value" is the bound variable! } } var textToDisplay = prompt('text to show in a second', 'foo bar'); // this returns a function that sets the bodys innerHTML to the prompted value var myFunction = getFunctionTextInASecond(textToDisplay); window.setTimeout(myFunction, 1000); 

myFunction, önceden tanımlanmış belirli bir parametreye sahip bir işlev döndürür!

Dürüst olmak gerekirse, ben 5.3 ve anonim işlevler / kapanışlar ile php çok daha fazla seviyorum. ad alanları daha önemli olabilir, ancak daha az seksidirler.

49
01 июля '09 в 0:38 2009-07-01 00:38 Cevap, 08 Temmuz 09: 09’da 0:38 tarihinde verildi. 2009-07-01 00:38

function () use () {} , PHP için bir kapatmadır, üst function değişkenini etkinleştirmek için use gerekir.

34
30 мая '15 в 17:45 2015-05-30 17:45 Cevap Steely Wing tarafından 30 Mayıs 15 'te 17: 45ta verilmektedir 2015-05-30 17:45

Zupa, "use" kullanarak kapatmayı ve EarlyBinding ile "kullanılan" değişkenlere referans arasındaki farkı açıklayan mükemmel bir iş yaptı.

Böylece, erken değişkenli bir bağlanma ile bir örnek kod yaptım (= kopya):

 <?php $a = 1; $b = 2; $closureExampleEarlyBinding = function() use ($a, $b){ $a++; $b++; echo "Inside \$closureExampleEarlyBinding() \$a = ".$a."<br />"; echo "Inside \$closureExampleEarlyBinding() \$b = ".$b."<br />"; }; echo "Before executing \$closureExampleEarlyBinding() \$a = ".$a."<br />"; echo "Before executing \$closureExampleEarlyBinding() \$b = ".$b."<br />"; $closureExampleEarlyBinding(); echo "After executing \$closureExampleEarlyBinding() \$a = ".$a."<br />"; echo "After executing \$closureExampleEarlyBinding() \$b = ".$b."<br />";  ?> 

Bir değişkene referans veren bir örnek (değişkenin önündeki " sembolünü not edin);

 <?php $a = 1; $b = 2; $closureExampleReferencing = function() use (  $a++; $b++; echo "Inside \$closureExampleReferencing() \$a = ".$a."<br />"; echo "Inside \$closureExampleReferencing() \$b = ".$b."<br />"; }; echo "Before executing \$closureExampleReferencing() \$a = ".$a."<br />"; echo "Before executing \$closureExampleReferencing() \$b = ".$b."<br />"; $closureExampleReferencing(); echo "After executing \$closureExampleReferencing() \$a = ".$a."<br />"; echo "After executing \$closureExampleReferencing() \$b = ".$b."<br />";  ?> 
11
17 марта '15 в 4:05 2015-03-17 04:05 Cevap joronimo tarafından 17.03.2015 tarihinde 04:05 tarihinde eklendi 2015-03-17 04:05

$tax ve $total tutarı getTotal () işlevinin içindedir. Bunun içindeki geri arama işlevini çağırırsınız. Bu nedenle, use çağırmaya gerek yoktur.

0
26 июля '17 в 15:55 2017-07-26 15:55 Cevap kullanıcı8278407 26 Temmuz 17, 15:55 2017-07-26 15:55 tarihinde verilmiştir.

etiketleriyle ilgili diğer sorular veya bir soru sorun