【PHP・Laravel】クラス内のstaticの意味と使い方まとめ

LaravelなどPHPファイルのクラスの中で使われている`static`という記載の使い方について。

変数（プロパティ）に適用する場合と、メソッドに適用する場合の２パターンがある。

##目次

1. [staticの意味](#staticの意味)
1. [staticはいつ使うか？](#staticはいつ使うか)
1. [staticの使い方](#staticの使い方)
1. [アクセス権限の種類](#アクセス権限の種類)
1. [staticプロパティの設定例](#staticプロパティの設定例)
1. [staticメソッドの設定例](#staticメソッドの設定例)
1. [メソッドを呼び出す時の注意点](#メソッドを呼び出す時の注意点)


<br>
##staticの意味
静的という意味。

通常クラスの中で定義した変数（プロパティ）やメソッドを呼び出すためにはインスタンスを生成する必要がある。元々存在しないものを生み出すのでこれはdynamic（動的）といえる。

一方、static(静的)では、**インスタンスを生成せずクラスを直接指定して、変数やインスタンスを呼び出せる**ようにできる。（←★超重要）



<br>
##staticはいつ使うか？
アプリケーションの中で**複数回登場する関数やプロパティを定義するときに使える**。

ヘルパーも似た機能だが、ヘルパーの場合は作成したメソッド名をどこでも呼び出せるのに対し、staticはそのクラスを呼び出した場合のみで使える。

プロパティ名やメソッド名が被りそうな場合や、**ある特定の目的のプロパティやメソッドをまとめる場合に使うと便利**。

（参考）[Laravel:ヘルパ関数の作り方](https://qiita.com/yuta-38/items/5e20964ab1991470bc7f)



<br>
##staticの使い方

**・変数への適用**
`[アクセス権限] static $変数名 = 値;`

アクセス権限は必須。verで定義した場合は`public`になる。

**・メソッドへの適用**
`[アクセス権限] static function メソッド名(){};`

アクセス権限がない場合はpublicと同じになる。


<br>
##アクセス権限の種類
アクセス権限は縛りの強い順に以下のようになる。

1. **private**  :定義したクラス内のみ
1. **protected** :継承クラス（子クラス）からもアクセス可能
1. **public** :クラスの外からアクセス可能
1. 記載なし(function) :publicと同じ
1. 記載なし(プロパティをvarで定義) :publicと同じ

https://www.php.net/manual/ja/language.oop5.visibility.php


<br>
##staticプロパティの設定例

###クラスを直接指定して呼び出した場合
TestClassを作成して、通常のクラスプロパティとstaticプロパティを作成し、それぞれをクラスの外から呼び出してみる。

```php:testClass.php
<?php

class TestClass{
  public $name = "名前";
  public static $staticName = "staticな名前";
}

//クラスの外で呼び出し
echo TestClass::$staticName;
staticな名前

echo TestClass::$name;
//Warning: Uncaught Error: 
//Access to undeclared static property: 
//TestClass::$name in php shell code:1
```

・`TestClass::$staticName;`は値を呼び出すことができた。
・`TestClass::$name;`はエラーになった。（インスタンスを生成してないので存在しない）



###インスタンスを生成して呼び出した場合
今後はインスタンスを生成してそれぞれの値を呼び出してみる。

```php:testClass.php

class TestClass{
  public $name = "名前";
  public static $staticName = "staticな名前";
}

//クラスの外でインスタンス生成し呼び出し
$test = new TestClass;

echo $test->staticName;
//（何も表示されない）

echo echo $test->name;
名前
```

・`staticName`はインスタンスの中にないので空。
・`name`はデフォルトの「名前」が呼び出される。




<br>
##staticメソッドの設定例
メソッドの場合もstaticを付ければクラスの外からインスタンス（オブジェクト）を生成せずに呼び出せる。

```php:testClass.php
class TestClass{

  public function test(){
    echo "インスタンスメソッド";
  }
  public static function testStatic(){
    echo "staticメソッド";
  }
}


//メソッドの呼び出し
TestClass::testStatic();
//"staticメソッド"

TestClass::test();

//インスタンスメソッドの呼び出し
$obj = new TestClass;
$obj->test();
//インスタンスメソッド
```


<br>
##メソッドを呼び出す時の注意点
**staticメソッドの中でインスタンスプロパティを呼び出すことはできない。**

`static function`と`$this->インスタンスプロパティ名`の組み合わせはエラーになる。

```php:NG例
class Static{
  public $name = "名前";
  public static $staticName = "static名前";

  //staticメソッドの中にインスタンスプロパティが入っているとエラーになる。
  public function static staticFunc(){
      echo self::$staticName;
      echo $this->name;
  }
}

$obj = new Static;
$obj->staticFunc();
//Warning: Uncaught Error: 
//Call to undefined method Dynamic::staticFunc() in php shell code:1

Static::saticFunc();
//Warning: Uncaught Error: 
//Call to undefined method Dynamic::staticFunc() in php shell code:1
```

<br>
**▼OK事例**
メソッドにstaticがなければ、インスタンスプロパティを呼び出せる。

```php:OK
class Dynamic{
  public $name = "名前";
  public static $staticName = "static名前";

  public function dynamicFunc(){
      echo self::$staticName;
      echo $this->name;
  }
}

$obj = new Dynamic;
$obj->dynamicFunc();
//static名前名前

Dynamic::dynamicFunc()
//（出力なし・・・staticメソッドが存在しない）
```

・自分のクラスの中でクラス自身を呼び出す場合は`self::`を使う。

・インスタンスプロパティを呼び出す場合はオブジェクトとして`$this`を使う。