Kata kunci `statis` di dalam fungsi?

110

Saya melihat sumber Drupal 7, dan saya menemukan beberapa hal yang belum pernah saya lihat sebelumnya. Saya melakukan beberapa pencarian awal di manual php, tetapi tidak menjelaskan contoh-contoh ini.

Apa yang dilakukan kata kunci staticterhadap variabel di dalam fungsi?

function module_load_all($bootstrap = FALSE) {
    static $has_run = FALSE
pengguna151841
sumber

Jawaban:

155

Itu membuat fungsi mengingat nilai variabel yang diberikan ( $has_rundalam contoh Anda) di antara beberapa panggilan.

Anda dapat menggunakan ini untuk tujuan yang berbeda, misalnya:

function doStuff() {
  static $cache = null;

  if ($cache === null) {
     $cache = '%heavy database stuff or something%';
  }

  // code using $cache
}

Dalam contoh ini, ifhanya akan dijalankan sekali. Bahkan jika beberapa panggilan ke doStuffakan terjadi.

Yoshi
sumber
4
Selain itu, jika fungsi telah dijalankan sekali, itu tidak akan mengatur ulang nilai $cachemenjadi nullpada panggilan berikutnya, bukan?
pengguna151841
7
@ user151841 $cachehanya akan disetel ulang di antara permintaan. Jadi ya, itu tidak akan diatur ulang pada panggilan berikutnya dalam permintaan yang sama (atau eksekusi skrip).
Yoshi
14
@Muhammad karena itulah kata kunci statis .
Yoshi
2
Saya percaya ifpemeriksaan kondisi $cache === nullakan dijalankan setiap kali fungsi ini dipanggil, tidak dipikirkan jika kode blok $cache = '..'akan dieksekusi.
Aivaras
apa yang terjadi jika fungsinya adalah metode di kelas, apakah variabel statis dibagikan antar instance?
santiago arizti
83

Sepertinya tidak ada yang menyebutkan sejauh ini, bahwa variabel statis di dalam instance berbeda dari kelas yang sama tetap statusnya. Jadi berhati-hatilah saat menulis kode OOP.

Pertimbangkan ini:

class Foo
{
    public function call()
    {
        static $test = 0;

        $test++;
        echo $test . PHP_EOL; 
    }
}

$a = new Foo();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3


$b = new Foo();
$b->call(); // 4
$b->call(); // 5

Jika Anda ingin variabel statis mengingat statusnya hanya untuk instance kelas saat ini, Anda sebaiknya tetap menggunakan properti kelas, seperti ini:

class Bar
{
    private $test = 0;

    public function call()
    {
        $this->test++;
        echo $this->test . PHP_EOL; 
    }
}


$a = new Bar();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3


$b = new Bar();
$b->call(); // 1
$b->call(); // 2
Yang
sumber
1
Aduh! Ini telah menggigit saya lebih dari sekali. Saya mengharapkan statis untuk diterapkan ke contoh saja, memberikan memoization; Namun cara berpikir itu salah, karena "statis" dalam konteks kelas berarti bagi kelas secara keseluruhan. Properti, metode, DAN variabel.
systemovich
14

Diberikan contoh berikut:

function a($s){
    static $v = 10;
    echo $v;
    $v = $s;
}

Panggilan pertama

a(20);

akan menampilkan 10, lalu $vmenjadi 20. Variabel $vtidak dikumpulkan sampah setelah fungsi berakhir, karena ini adalah variabel statis (non-dinamis). Variabel akan tetap dalam ruang lingkupnya sampai skrip benar-benar berakhir.

Oleh karena itu, panggilan berikut ini

a(15);

kemudian akan menampilkan 20, dan kemudian disetel $vmenjadi 15.

mauris
sumber
9

Statis bekerja dengan cara yang sama seperti di kelas. Variabel dibagikan di semua contoh fungsi. Dalam contoh khusus Anda, setelah fungsi dijalankan, $ has_run disetel ke TRUE. Semua fungsi yang berjalan di masa mendatang akan memiliki $ has_run = TRUE. Ini sangat berguna dalam fungsi rekursif (sebagai alternatif untuk meneruskan hitungan).

Variabel statis hanya ada dalam lingkup fungsi lokal, tetapi tidak kehilangan nilainya ketika eksekusi program meninggalkan ruang lingkup ini.

Lihat http://php.net/manual/en/language.variables.scope.php

tofutim
sumber
3

variabel statis dalam suatu fungsi berarti bahwa tidak peduli berapa kali Anda memanggil fungsi tersebut, hanya ada 1 variabel.

<?php

class Foo{
    protected static $test = 'Foo';
    function yourstatic(){
        static $test = 0;
        $test++;
        echo $test . "\n"; 
    }

    function bar(){
        $test = 0;
        $test++;
        echo $test . "\n";
    }
}

$f = new Foo();
$f->yourstatic(); // 1
$f->yourstatic(); // 2
$f->yourstatic(); // 3
$f->bar(); // 1
$f->bar(); // 1
$f->bar(); // 1

?>
Pwnna
sumber
3

Untuk memperluas jawaban Yang

Jika Anda memperluas kelas dengan variabel statis, masing-masing kelas yang diperluas akan menyimpan statis yang direferensikan "sendiri" yang dibagikan di antara instance.

<?php
class base {
     function calc() {
        static $foo = 0;
        $foo++;
        return $foo;
     }
}

class one extends base {
    function e() {
        echo "one:".$this->calc().PHP_EOL;
    }
}
class two extends base {
    function p() {
        echo "two:".$this->calc().PHP_EOL;
    }
}
$x = new one();
$y = new two();
$x_repeat = new one();

$x->e();
$y->p();
$x->e();
$x_repeat->e();
$x->e();
$x_repeat->e();
$y->p();

keluaran:

satu: 1
dua : 1
satu: 2
satu : 3 <- x_repeat
satu: 4
satu : 5 <- x_repeat
dua : 2

http://ideone.com/W4W5Qv

Tschallacka
sumber
1

Di dalam fungsi, staticberarti variabel akan mempertahankan nilainya setiap kali fungsi dipanggil selama masa pemuatan halaman.

Oleh karena itu dalam contoh yang Anda berikan, jika Anda memanggil suatu fungsi dua kali, jika disetel $has_runke true, maka fungsi tersebut akan dapat mengetahui bahwa fungsi tersebut sebelumnya telah dipanggil karena $has_runakan tetap sama dengan truesaat fungsi dimulai untuk kedua kalinya.

Penggunaan statickata kunci dalam konteks ini dijelaskan dalam manual PHP di sini: http://php.net/manual/en/language.variables.scope.php

Spudley
sumber