【PHP入門】クラス変数・クラスメソッドを使用する方法(static)

PHPでは、JavaやC#のようなブログラミング言語同様にstaticを使用して静的メンバを指定することができます。

この記事では、

・PHPのクラスの構造
・静的なメンバとstatic

という基本的な内容から、

・staticを使う際の注意点

で、気をつけなくてはならない点について言及します。

今回はそんなstaticを使用する方法について、わかりやすく解説します!

PHPのクラスの構造

staticについて説明する前に、オブジェクト指向言語としてのPHPについて軽く復習しておきましょう。

class宣言

まず、クラスと呼ばれる型の宣言を行います。

class (クラス名){
    …
}

クラスは動作を表すメソッドと、データを表すプロパティからなります。

このクラスをもとに、インスタンスを生成します。書式は以下の通りです。

(インスタンス名) = new (クラス名)

インスタンスを生成したら

(インスタンス名)->(プロパティ名)
(インスタンス名)->(メソッド名)

といった形でプロパティ、ならびにメソッドにアクセスします。

では実際にサンプルを見てみましょう。

<?php

// Studentというクラス(型)を宣言。クラスの1文字目は大文字
class Student {

  // プロパティ
  public $name;
  public $age;
  //  メソッド
  function showData(){
      echo $this->name." is ".$this->age." years old.<br/>";
  }

}

//クラスStudentのインスタンスを作成
$tanaka = new Student;

//(インスタンス名)->(プロパティ名)  ※プロパティの"$"はつけない
//tanakaというインスタンスのプロパティ$nameに、tanakaを挿入。
$tanaka->name = "tanaka";
$tanaka->age = 12;

echo $tanaka->name."<br/>";
echo $tanaka->age."<br/>";

$tanaka->showData();
tanaka
12
tanaka is 12 years old.

静的メンバと動的メンバ

通常クラスへアクセスするには、new演算子を使用してクラスのインスタンスを生成する必要があります。

しかし、クラスのインスタンスを生成しなくても、クラスのメンバにアクセス可能なメンバのことを静的(static)メンバと呼びます。

言語によってはクラスメンバと言う場合もあります。その際、メソッドの場合はクラスメソッド、プロパティをクラス変数などと呼びます。

静的(static)メンバを使用するためには、変数や関数、メソッドの先頭にstaticを記述する必要があります。

staticな変数を定義する場合、以下のように記述します。

クラス名{
  static $変数名 = 値;
  //処理
}

また、staticの前にはpublicprivateなどのアクセス権を指定することができます。

アクセス権を指定すれば、staticのメンバがどこからでもアクセスできるようになったり、逆にアクセスを限定するようなことが可能となります。

public static $変数名 = 値;

なおPHPのclassのさまざまな処理については、以下の記事にまとめていますので、ぜひ参考にしてください。


【PHP入門】クラスの使い方まとめ
更新日 : 2018年9月4日

静的なメンバとstatic

ここでは静的(static)なメンバの使用方法について紹介します。

static変数の使い方

通常クラスの変数は外部から参照するためには、クラスのインスタンスを生成してクラスの関数や変数などにアクセスします。

しかし、前述したようにstaticを使用すれば、クラスのインスタンスを生成しないで直接クラスのメンバにアクセスすることができます。

これは、staticを指定した変数や関数・メソッドはクラスそのものに属することなり、インスタンスとの関わりがなくなるからです。

以下にstaticな変数を定義して、クラス外からインスタンスを生成しないで参照する方法を記述します。

<?php
 
class Foo {
 
  //静的変数を作成する
  public static $val = 10;
}
 
//静的変数を参照する
$value = Foo::$val;
echo $value;
 
?>

実行結果

10

実行結果のとおり、クラスFooのインスタンスを生成しないで、クラス内の静的メンバにアクセスできることがわかりますね!

staticな変数の活用法として、ローカルな変数では関数内でセットした値は関数の外に出たら値はリセットされてしまいますが、staticな変数を関数内で定義した場合、セットした値は処理が関数外に移っても保持されます。

以下の例では、関数を呼び出すごとにstaticな変数の値をインクリメントしています。

<?php
 
function Foo(){
  static $val = 0;
  echo $val.'<br>';
 
  $val++;
}
 
Foo();
Foo();
Foo();
 
?>

実行結果

0
1
2

実行結果のとおり、関数を呼び出すごとに値がインクリメントされていることがわかりますね!

これがstaticを指定しないローカルな変数だったら、毎回0が出力されてしまいます

なお、クラス内で生成したstaticでない通常の変数を静的にアクセスしようとすると、エラーが発生しますので注意しましょう。

逆に静的なメンバは、クラスのインスタンスから参照するときに使用する矢印演算子->によるアクセスはできません。

staticな配列の指定方法

配列をstaticなメンバとして定義することも可能です。

以下に配列をstaticとして定義して、クラス外から参照する方法を記述します。

<?php
 
class fruitsClass{
  //静的な配列を定義する
  public static $fruits_array = ['apple', 'orange', 'melon', 'banana', 'pineapple'];
}
 
//静的な配列を参照する
$array = fruitsClass::$fruits_array;
 
foreach($array as $value){
  echo $value;
  echo '<br>';
}
 
?>

実行結果

apple
orange
melon
banana
pineapple

実行結果のとおり、配列もインスタンス化しないでstaticなメンバとしてアクセスできることがわかりましたね。

配列もstatic修飾子を使用することにより、ローカルから外に処理が移行しても、値はそのまま保持されますので、処理によって使い分けるとよいでしょう。

なお、変数や配列などをクラス内で定数化したい場合はconstを使用します。

constの使い方については、以下の記事で詳しく解説しています!

【PHP入門】defineで定数を定義する方法
更新日 : 2019年2月12日

staticなメソッド

staticを使用してメソッドを静的にアクセスすることもできます。

以下にstaticなメソッドを定義して、クラス外からアクセスする方法を記述します。

<?php

class SamuraiClass {

  //静的なメソッドを使用する
  public static function SamuraiMethod($val) {
    $val = 'Samurai '.$val;
    return $val;
  }
}

//静的なメソッドを参照する
$name = SamuraiClass::SamuraiMethod('Engineer');

echo $name;
 
?>

実行結果

Samurai Engineer

このようにstaticを使用すれば、気軽に関数やメソッドにアクセスすることが可能となります。

staticを使う際の注意点

このように便利なstaticですが、使うときには注意しなくてはならない点がいくつかあります。

以下、それらについて説明していきましょう。

動的メンバと静的メンバの関係性

静的なメソッドおよび静的なプロパティは、動的なメソッド・プロパティにアクセスできます。

しかし、動的なメソッド・プロパティから静的メソッド、プロパティにアクセスすることは出来ません。

例えば、以下のようなクラスはエラーになります。

<?php

class Foo{
    public static $n = "static";
    public $m = "instance";
    //  静的メソッドから動的プロパティを呼び出す
    public static function show(){
        echo Foo::$n;    //  静的プロパティ
        echo $this->m;    //  動的プロパティ
    }
    
}

Foo::show();
Fatal static Fatal error: Using $this when not in object context in /home/ubuntu/workspace/Err.php on line 9

動的プロパティはインスタンスを作らなければ使えません。

継承と静的メソッド

また、継承の際にも気をつけなくてはならない点があります。

インスタンスメソッドにはオーバーライドと言う概念があります。

これは、サブクラスの中でスーパークラスのメソッドを上書きできるというものですが、静的メソッドの場合はこれが当てはまりません

<?php

// スーパークラス
class MyParent
{
    static function foo()
    {
        return "Super";
    }

    static function bar()
    {
        echo self::foo() ."<br/>";
    }
}

// サブクラス
class MyChild extends  MyParent
{
    // スーパーのメソッドをオーバーライド
    static function foo()
    {
        return "Sub";
    }
}

MyParent::bar();    # <= "Super"と出力してほしい
MyChild::bar();     # <= "Sub"と出力してほしい
Super
Super

サブクラスでオーバーライドしたfoo()が呼ばれず、スーパークラスのfoo()が呼ばれています。

selfは、self::が記載されたクラス内のプロパティやメソッドを呼び出すのに使われます。

したがって、スーパークラス内では、”Parent”が、サブクラス内では”Sub”が取得されるはずです。

ところが実際は、サブクラスからスーパークラスの静的メソッドを呼び出した場合、そのメソッドは親クラスのコンテキストで実行されてしまいます。

そのため、サブクラスから呼び出したスーパークラスのstaticなメソッド内でサブクラスでオーバーライドされたメソッドを呼び出そうとしても、親クラスで定義されたものが呼ばれる結果になります。

このように、staticを使う際には意外な落とし穴がありますので、気をつけてください。

なお、PHPの継承については、以下の記事で詳しく説明しています。興味のある方はこちらもあわせてみてください。

【PHP入門】継承(extends)、トレイト(trait)を使いこなそう!
更新日 : 2019年5月2日

まとめ

ここでは静的メンバの意味やstaticを使用した変数やクラス、メソッド、配列などの使い方について解説しました。

静的メンバはクラスをインスタンス化しなくても、簡単にクラスのメンバにアクセスして、値を参照できたりすることが可能ですので、この機会にぜひ覚えておきましょう。

もしstaticの使い方忘れてしまったら、この記事を思い出してくださいね。

LINEで送る
Pocket

「プログラミング、右も左もわからない…」という方にオススメ

当プログラミングスクール「侍エンジニア塾」では、これまで6000人以上のエンジニアを輩出してきました。

その経験を通してプログラミング学習に成功する人は、「目的目標が明確でそれに合わせた学習プランがあること」「常に相談できる人がそばにいること」「自己解決能力が身につくこと」この3つが根付いている傾向を発見しました。

侍エンジニア塾は上記3つの成功ポイントを満たすようなサービス設計に磨きをかけております。

cta_under_bnr

「自分のスタイルや目的に合わせて学習を進めたいな」とお考えの方は、ぜひチェックしてみてください。

書いた人

ヤマシタ

システムエンジニアとして10年勤務→フリーランスへ。現在は侍ブログ編集部としてこれまでに200記事以上の記事を執筆。
大規模システム開発からWebアプリ開発まで経験あり。最近ではPythonの機械学習に挑戦中。