生PHPについて知識を資産化していく⑤

#前提として

+ 自分が勉強してきた知識を保存するために書いています。
+ 本当に初歩的な事から書いていってます。
+ 万が一間違っている可能性もございますので、その時はご指摘頂ければ嬉しいです。
+ 常時更新していく予定です。
+ アウトプット用ですので、MAMPを使用していきます。

####PHPについての記事はこちらから

+ [生PHPについて知識を資産化していく①](https://qiita.com/shotee/items/9d82034a0b2960c7b4cf)
+ [生PHPについて知識を資産化していく②](https://qiita.com/shotee/items/a23ae54814fa36289cb2)
+ [生PHPについて知識を資産化していく③](https://qiita.com/shotee/items/2fa14f5ae06b6c4adec2)
+ [生PHPについて知識を資産化していく④](https://qiita.com/shotee/items/345da9bfa086c82c3e33)


##オブジェクト指向

オブジェクト指向とは → 役割分担

例：会社で考えてみる

```
会社
↓
部門毎に分ける
↓
・営業
・総務
・開発
・経営
・PR
```

###オブジェクト指向の3要素

```
・カプセル化
・継承
・ポリモーフィズム(多様化)
```

+ php.net：[クラスの基礎](https://www.php.net/manual/ja/language.oop5.basic.php)
+ [PHPオブジェクト指向　~前半~](https://qiita.com/mpyw/items/41230bec5c02142ae691)

##それぞれの特徴

| タイプ | 宣言 | インスタンス化 | 利用 | アクセス修飾子 | 特徴 |
|:-----------:|:------------:|:------------:|:------------:|:------------:|:------------:|
| 具象クラス       | class        | ○         | extends | public, protected, private | 単一継承 |
| 抽象クラス     | abstract<br>class      | ×       | extends | public, protected, private | 継承前提 |
| インターフェース       | interface       | ×         | implements | public | メソッド名のみ |
| トレイト         | trait          | ×           | use | public, protectec, private | 複数use |

+ [クラスから理解するPHPのオブジェクト指向]
(https://rightcode.co.jp/blog/become-engineer/php-object-orientation#i-5)
+ [オブジェクトの継承](https://www.php.net/manual/ja/language.oop5.inheritance.php)


##オブジェクト指向のコツ

```
・用語・使い方を知る
・ソースを読む
・デザインパターンを知る
```

+ [PHPで学ぶデザインパターン - オブジェクト指向の基礎](https://qiita.com/bmf_san/items/d07291f6ce867688cb95)


##モダンPHP


```
最近のPHP

・PSR-1,2,4(PHPコーディング規約)
・namespace(名前空間)
・autoload(自動クラス読み込み)
・composer(PHPライブラリ管理+オートロード)
```

+ [PHPコーティング規約](https://www.wakuwakubank.com/posts/416-php-psr/)
+ [PHPのPSR-0とPSR-4でautoloaderの違いと名前空間の基礎](https://qiita.com/KEINOS/items/2924ecde3e4bab0ead7e)

##クラスの関係図

![クラスの関係図]
(https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556828/de719807-0735-5ad7-f0b6-128c510bb9f6.png)





###インスタンス

+ private(外からアクセスできない)
+ protected(自分・継承したクラス)
+ public(公開)

this(このクラス)

「new」でインスタンス化をする

```object/instance.php
<?php

class Product { //頭を大文字にする

  // アクセス修飾子(private, protected, public)

  // 変数
  private $product = [];

  // 関数

  function __construct($product) // 初回に呼び出す
  {
    $this->product = $product; // productは、変数の$productのこと。「$」がつかないので注意)
  }

  public function getProduct()
  {
    echo $this->product; // このクラスの中の変数(product)を呼び出す
  }

  public function addProduct($item)
  {
    $this->product .= $item; // このクラスの中の変数(product)に、引数($item)を追加する
  }

  public static function getStaticProduct($str)
  {
    echo $str;
  }

}

// 「new」でインスタンス化する
$instance = new Product('テスト');

// getProduct()関数を呼び出す
$instance->getProduct();
echo '<br>';

$instance->addProduct('追加分');
echo '<br>';

$instance->getProduct();
echo '<br>';

// 静的(static) クラス::関数名
Product::getStaticProduct('静的');
echo '<br>'

?>
```



###継承

継承させることで、親クラスが持っている変数や関数を子クラスが使うことができる

####オーバーライド

```
上書き。
親クラスに関数を作成しておいて、同じ名前で子クラスに関数を作成すると、上書きされる
```

```object/extends.php
<?php

// 親クラス
class BaseProduct {
  // 変数 関数
  public function echoProduct() {
    echo '親クラスです';
  }

  // オーバーライド(上書き)
  public function getProduct() { // 子クラスにも同じ関数があるので子クラスに上書きされる
    echo '親の関数です';
  }
}

// 子クラス
class Product extends BaseProduct { //頭を大文字にする

  // アクセス修飾子(private, protected, public)

  // 変数
  private $product = [];

  // 関数

  function __construct($product) // 初回に呼び出す
  {
    $this->product = $product; // productは、変数の$productのこと。「$」がつかないので注意)
  }

  public function getProduct()
  {
    echo $this->product; // このクラスの中の変数(product)を呼び出す
  }

  public function addProduct($item)
  {
    $this->product .= $item; // このクラスの中の変数(product)に、引数($item)を追加する
  }

  public static function getStaticProduct($str)
  {
    echo $str;
  }

}

// 「new」でインスタンス化する
$instance = new Product('テスト');

// getProduct()関数を呼び出す
$instance->getProduct();
echo '<br>';

// 親クラスのメソッド
$instance->echoProduct(); // 親クラスです と表示
echo '<br>';

$instance->addProduct('追加分'); // テスト追加分 と表示
echo '<br>';

$instance->getProduct();
echo '<br>';

// 静的(static) クラス::関数名
Product::getStaticProduct('静的');
echo '<br>'

?>
```

+ [PHP オーバーライドのサンプル](https://itsakura.com/php-override)


###抽象クラス

+ インスタンスを生成することができない。
+ 関数の中身が書けない。関数名のみつけれる
+ 抽象メソッドは絶対に使わないといけない


```object/abstract.php
// 抽象クラス // 設定するメソッドを強制
abstract class ProductAbstract {
  // 変数 関数
  public function echoProduct() {
    echo '親クラスです';
  }

  abstract public function getProduct();
}

// 子クラス
class Product extends ProductAbstract { //頭を大文字にする

  // アクセス修飾子(private, protected, public)

  // 変数
  private $product = [];

  // 関数

  function __construct($product) // 初回に呼び出す
  {
    $this->product = $product; // productは、変数の$productのこと。「$」がつかないので注意)
  }

  public function getProduct()
  {
    echo $this->product; // このクラスの中の変数(product)を呼び出す
  }

  public function addProduct($item)
  {
    $this->product .= $item; // このクラスの中の変数(product)に、引数($item)を追加する
  }

  public static function getStaticProduct($str)
  {
    echo $str;
  }

}

// 「new」でインスタンス化する
$instance = new Product('テスト');

// getProduct()関数を呼び出す
$instance->getProduct();
echo '<br>';

// 親クラスのメソッド
$instance->echoProduct(); // 親クラスです と表示
echo '<br>';

$instance->addProduct('追加分'); // テスト追加分 と表示
echo '<br>';

$instance->getProduct();
echo '<br>';

// 静的(static) クラス::関数名
Product::getStaticProduct('静的');
echo '<br>'

?>
```

+ php.net[クラスの抽象化](https://www.php.net/manual/ja/language.oop5.abstract.php)


###インターフェース

メソッドの内容しか書けない

```object/interface.php
<?php

// インターフェース
interface ProductInterface {

  public function getProduct();
}

// インターフェース
interface NewsInterface {
  
  public function getNews();
}

// 親クラス、具象クラス
class BaseProduct {
  // 変数 関数
  public function echoProduct() {
    echo '親クラスです';
  }

  // オーバーライド(上書き)
  public function getProduct() { // 子クラスにも同じ関数があるので子クラスに上書きされる
    echo '親の関数です';
  }
}

// 子クラス // インターフェースの場合は継承を複数適用できる
class Product implements ProductInterface, NewsInterface { 

  // アクセス修飾子(private, protected, public)

  // 変数
  private $product = [];

  // 関数

  function __construct($product) // 初回に呼び出す
  {
    $this->product = $product; // productは、変数の$productのこと。「$」がつかないので注意)
  }

  public function getProduct()
  {
    echo $this->product; // このクラスの中の変数(product)を呼び出す
  }

  public function addProduct($item)
  {
    $this->product .= $item; // このクラスの中の変数(product)に、引数($item)を追加する
  }

  public function getNews() {
    echo 'ニュースです';
  }

  public static function getStaticProduct($str)
  {
    echo $str;
  }

}

// 「new」でインスタンス化する
$instance = new Product('テスト');

// getProduct()関数を呼び出す
$instance->getProduct();
echo '<br>';

Product(); // 親クラスです と表示
// echo '<br>';

$instance->addProduct('追加分'); // テスト追加分 と表示
echo '<br>';

$instance->getProduct();
echo '<br>';

$instance->getNews();
echo '<br>';

// 静的(static) クラス::関数名
Product::getStaticProduct('静的');
echo '<br>'

?>
```

php.net:[オブジェクト インターフェース](https://www.php.net/manual/ja/language.oop5.interfaces.php)


###トレイト

トレイト(trait)は、複数useができる。

```object/trait.php
<?php

trait ProductTrait {
  public function getProduct() {
    echo 'プロダクト';
  }
}

trait NewsTrait {
  public function getNews() {
    echo 'ニュース';
  }
}

class Product {

  use ProductTrait;
  use NewsTrait;

  public function getInformation() {
    echo 'クラスです';
  }

  // オーバーライドした時に表示(クラスの方のメソッドが優先される)
  public function getNews() {
    echo 'クラスのニュースです';
  }

}

// インスタンス化する
$product = new Product();

$product->getInformation(); // クラスです と表示
echo '<br>';

$product->getProduct(); // プロダクト と表示
echo '<br>';

$product->getNews(); // ニュース と表示(オーバーライド時は クラスのニュースです と表示)
echo '<br>';


?>
```

php.net:[トレイト](https://www.php.net/manual/ja/language.oop5.traits.php)


##composer

ターミナルでcomposerを入れていく

```
①MAMPでこれまで作成したフォルダに移動する
$ cd Applications/MAMP/htdocs/***

※ ***はフォルダ名です

②フォルダ内に、composerを入れるフォルダを作成する
$ mkdir composertest
(フォルダ名は任意でOK)

③作成したフォルダに移動する
cd composertest

④composer.jsonファイルを作成する
$ composer init

※composer を使うには composer.json という設定ファイルがあり、作成する必要がある

⑤作成した conposertestフォルダ内に composer.json が作成させる
```

###autoloadができるように書き換える

```composertest/composer.json
{
    "autoload": {
        "psr-4": { // autoloadのコーディング規約
            "App\\" : "app/"  // namespace : 実際のフォルダ
        }
    }
}
```

ターミナルでcomposerをインストールする

```
$ composer install
```

composer.jsonで設定した内容にしたがって、venderフォルダの中がインストールされる

####ファイルを更新したり、内容を変えたりした場合はターミナルで更新する

```
$ composer update

$ composer dump-autoload
```

+ [composer install と composer updateの違い](https://qiita.com/YusukeHigaki/items/47dd3ec23544225f7301)
+ [PHPのオートロード(autoload)](https://qiita.com/atwata/items/5ba72d3d881a81227c2a)


###モデルとコントローラファイルを書いていく

####モデル

```composertest/app/Models/TestModel.php
<?php

namespace App\Models; // フォルダと同じ構成になる

class TestModel // classの名前が、ファイルの名前と同じにする
{
  private $text = 'hello world';

  public function getHello() {
    return $this->text;
  }
}

?>
```

####コントローラ

```composertest/app/Controllers/TestController.php
<?php

namespace App\Controllers; // フォルダと同じ構成になる

use App\Models\TestModel; // TestModel.phpを読み込む

class TestController // classの名前が、ファイルの名前と同じにする
{
  public function run() {
    $model = new TestModel; //TestModel.phpを読み込んでいるので、インスタンス化ができる
    echo $model->getHello(); // TestModel.phpのgetHello()関数をControllerから呼び出す
  }
}

?>
```

####ブラウザに表示させる

```composertest/index.php
<?php

// 一度だけautoloadファイルを読み込む必要がある
require_once __DIR__ . '/vendor/autoload.php';

use App\Controllers\TestController;

$app = new TestController; // インスタンス化
$app->run(); // TestController.phpで作成したrunメソッド

?>

// hello world と表示される
```

+ [composer 公式](https://getcomposer.org/)
+ [Composerの使い方](https://qiita.com/sano1202/items/50e5a05227d739302761)


###ライブラリを管理する

####Carbon

```
・ PHPのDateTimeクラスを継承して拡張された日時操作ライブラリ
・ 英語圏の時刻表記とかもしてくれる（8/10/2016みたいに日本とは順番が違うのでちょっと面倒）
・ Laravelには標準搭載
・ 直接ダウンロードかComposerでインストール可能
```

####ターミナルでインストールする

```composertest
$ composer require nesbot/carbon
```

composer.jsonにCarbonのライブラリが入っていることを確認する

```composertest/composer.jsom
{
    "autoload": {
        "psr-4": { 
            "App\\" : "app/"
        }
    },
    "require": {
        "nesbot/carbon": "^2.46"  // ライブラリが入っているのを確認
    }
}

```

####実際に使う

```composertest/index.php
<?php

// 一度だけautoloadファイルを読み込む必要がある
require_once __DIR__ . '/vendor/autoload.php';

use Carbon\Carbon; //クラスを持ってくる

echo Carbon::now(); //現在の日付が表示される

// 例：　2021-04-06 15:38:06　と表示
?>
```

他にも表示の仕方はありますので、詳しくはこちら
↓↓
+ [【php】日付操作ライブラリCarbonを使ってみよう](https://qiita.com/shosho/items/ea049f2a28586364e35c)

他にも別のライブラリがある

+ [PHP 開発が爆捗る PHP ライブラリ9選](https://blog.codecamp.jp/php_library)
+ [「目的に応じて適材適所で使うPHPライブラリ」連載一覧](https://codezine.jp/article/corner/328)


####PHPについての記事はこちらから

+ [生PHPについて知識を資産化していく①](https://qiita.com/shotee/items/9d82034a0b2960c7b4cf)
+ [生PHPについて知識を資産化していく②](https://qiita.com/shotee/items/a23ae54814fa36289cb2)
+ [生PHPについて知識を資産化していく③](https://qiita.com/shotee/items/2fa14f5ae06b6c4adec2)
+ [生PHPについて知識を資産化していく④](https://qiita.com/shotee/items/345da9bfa086c82c3e33)