関数内の `static`キーワード?


109

私はDrupal 7のソースを探していましたが、これまで見たことのないものを見つけました。私はphpのマニュアルを最初に見てみましたが、これらの例は説明されていませんでした。

キーワードstaticは関数内の変数に対して何をしますか?

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

回答:


155

これにより、関数$has_runは複数の呼び出し間で(例では)指定された変数の値を記憶します。

たとえば、次のようなさまざまな目的に使用できます。

function doStuff() {
  static $cache = null;

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

  // code using $cache
}

この例では、ifは1回だけ実行されます。複数の呼び出しdoStuffが発生する場合でも。


4
関数は一度実行された場合も、それはの値がリセットされません$cacheへのnull権利、後で呼び出しで?
user151841

7
@ user151841 $cacheはリクエスト間でのみリセットされます。つまり、同じ要求(またはスクリプトの実行)でのその後の呼び出しではリセットさません
ヨシ

14
@Muhammadは、staticキーワードが行うことだけです。
ヨシ

2
私は信じているif条件のチェックが$cache === nullのブロックコードがあればと思っていない、この関数が呼び出されるたびに実行されます$cache = '..'実行されます。
Aivaras

関数がクラスのメソッドである場合はどうなりますか?静的変数はインスタンス間で共有されますか?
サンティアゴアリズティ2018

83

これまで誰も言及していないようで、同じクラスの異なるインスタンス内の静的変数はその状態のままです。したがって、OOPコードを作成するときは注意してください。

このことを考慮:

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

静的変数に現在のクラスインスタンスの状態のみを記憶させたい場合は、次のようにクラスプロパティを使用することをお勧めします。

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

1
痛い!これは私を二度以上噛みました。静的はインスタンスにのみ適用され、メモを提供することを期待していました。しかし、それは間違った考え方でした。クラスの文脈における「静的」は、クラス全体にとって意味があるからです。プロパティ、メソッド、および変数。
systemovich

14

次の例の場合:

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

の最初の呼び出し

a(20);

出力され10、次に出力さ$vれます20。変数$vは静的(非動的)変数であるため、関数の終了後にガベージコレクションされません。スクリプトが完全に終了するまで、変数はスコープ内に留まります。

したがって、次の呼び出し

a(15);

その後、が出力され20、に設定さ$vれます15


9

Staticは、クラスの場合と同じように機能します。変数は、関数のすべてのインスタンスで共有されます。特定の例では、関数が実行されると、$ has_runがTRUEに設定されます。関数の今後の実行はすべて$ has_run = TRUEになります。これは、(カウントを渡す代わりに)再帰関数で特に役立ちます。

静的変数はローカル関数スコープにのみ存在しますが、プログラムの実行がこのスコープを離れても値は失われません。

http://php.net/manual/en/language.variables.scope.phpを参照してください


3

関数内の静的変数は、関数を何度呼び出しても、変数は1つしかないことを意味します。

<?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

?>

3

ヤンの答えを拡大する

静的変数を使用してクラスを拡張する場合、個々の拡張クラスは、インスタンス間で共有される「独自の」参照された静的を保持します。

<?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();

出力:

one:1
two:1
one:2
one:3 <-x_repeat
one:4
one:5 <-x_repeat
two:2

http://ideone.com/W4W5Qv


1

関数内でstaticは、ページが読み込まれる間、関数が呼び出されるたびに変数がその値を保持します。

したがって、指定した例では、関数を2回呼び出す場合、関数をに設定$has_runするtrueと、関数が2回目に起動$has_runしたtrueときと同じであるため、関数は以前に呼び出されたことを知ることができます。

staticこのコンテキストでのキーワードの使用法については、PHPマニュアル(http://php.net/manual/en/language.variables.scope.php)で説明されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.