PHPの基礎文法からピックアップ

#はじめに

最近私が勉強したPHPの基礎文法から個人的に覚えておきたいと感じた箇所をピックアップしていこうと思います。

##開始タグ
改行して2行目以降に記述いていきます。
phpのみの記述の場合閉じタグは書きません。

```php
<?php
```
##終了タグ、閉じタグ
```php
?>
```

##出力

```php
echo 'hoge';
```

**echo**
1つ以上の文字列を出力します。
リスト形式の引数を受け付け、返り値を持ちません。

```php
print 'hoge';
```

**print**
文字列を出力します。
複数の引数を指定できません。また返り値は常に1となります。

###echoとprintそれぞれの違いとは？

echoは複数の引数が取れるので以下のようなことができます。

```php
echo  "str", $a,  $b,  $c;
```

printは引数を一つしか取れないのでこのようなことはできません。

##.(ピリオド)
文字列の連結をします。
前後にスペースを空けると見やすくなります。

```php
'hello' . 'world' . 'ok'
```

##変数

```php
$name = 'john';
```

##定数(const)
定数は慣習的に大文字で、変数と違い$はつきません。
同じ名前で再代入できません。

```php
const NAME = 'john';
```

##定数(define)

```php
define('NAME', 'john'); // NAMEにjohnを代入
```
###constとdefineの違いは？
クラス定数はconst
それ以外はdefineで定義します。

##PHP_EOL
ターミナルで改行をします。

```php
$name = 'john';

echo 'Hello' . $name . PHP_EOL;
echo 'Hi' . $name . PHP_EOL . PHP_EOL;
```
PHP_EOLは定義済み定数です。
2個連続でつけると一行あけることができます。
\n と同じ意味ですが、\n は''(シングルクォーテーション)で使えません。

##'(シングルクォーテーション)と"(ダブルクォーテーション)

変数を埋め込まない場合はどちらをつかってもOKです。

「$name」という文字列や"(ダブルクォーテーション)を出力したいときは、シングルクォーテーションを使う必要があります。

```php
echo '$name'; // ○
echo "$name"; // x

echo 'hello!"bob"';
```

##長めのテキストを表現する方法

```php
<?php
  $text = <<<'EOT'
  ここに書いた文章の改行や字下げを保持したまま
     textという変数に
  代入してくれる
  EOT;
?>
```
'EOT' ←ここで必ず改行。コメントも書いてはいけません。
EOTでも”EOT”でもOK
”EOT”で変数も埋め込めます。

```php
// 変数を展開しない書き方をnowdoc(ナウドキュメント)
$text = <<<'EOT'
// 変数を展開する方の書き方はheredoc(ヒアドキュメント)と呼ぶ
$text = <<<"EOT"
```

EOTは終端記号と呼ばれます。
好きな名前でいいが例では「EndOfText」という意味でEOTとしています。

##データ型

| データ型          |      具体例|
|:-----------------|:------------------|
| 文字列（string）     | 'hello'   "world" |
| 整数（int）          | 5       -20|
| 浮動小数点数（float）| 3.2    -1.8|
| null             |null        |
| 真偽値（bool）      | true  false|
| 配列（array）      | [4, 1, 7]|
| オブジェクト（object）     |new object()|

##今扱っている変数の型がどの型か調べる
```php
var_dump() 
```
###例

```php
<?php

$a = 'hello';
$b = 15;
$c = -2.8;
$d = null;
$e = true;

var_dump($a);
var_dump($b);
var_dump($c);
var_dump($d);
var_dump($e);
```

###実行結果

```terminal
~ $ php main.php
string(5) "hello"
int(15)
float(-2.8)
NULL
bool(true)
```

##型を変換したい場合

```php

<?php

$a = 'hello';
$b = 15;
$c = -2.8;
$d = null;
$e = true;

// 値の前に () で型を指定してあげれば OK
$a = (float)15;
$b = (string)2.8;

var_dump($a);
var_dump($b);
```

###実行して確認

```terminal
~ $ php main.php
float(15)
string(3) "2.8"
```
##変数のスコープ

PHPでは関数の外で定義された変数を使うことは出来ないというルールがあります。
そこで変数に対して関数の外で定義されたという意味でglobalを付けます。

以下は買い物の計算結果（税込）を表しています。

```php
<?php

$rate = 1.1; // 10%の税

function sum($a, $b, $c)
{
  global $rate; // 関数の外で定義された変数
  return ($a + $b + $c) * $rate; // 計算結果に税をかける
}

echo sum(50, 100, 150) + sum(200, 400, 600) . PHP_EOL;
```

しかしこのglobalを使うとコードが長くなった時にどこで変数の値が変更されているか追いにくくなります。

そこでこの関数内で使う変数は引数で渡してあげるか、その関数内で定義します。

```php
<?php
######関数の外######
$rate = 1.1; // グローバルスコープ（関数の外全てで有効）
######関数の中######
function sum($a, $b, $c)
{
  $rate = 1.08; // ローカルスコープ（関数の中のみ有効）
  return ($a + $b + $c) * $rate; // 計算結果に税をかける
}

echo sum(50, 100, 150) + sum(200, 400, 600) . PHP_EOL;
```
こちらの計算結果は```$rate = 1.08;```が有効になり、
1.08の税率がかけられ1620になります。

---

このような変数の有効範囲を**スコープ**と呼びます。

関数の外にあるスコープは関数の外の全てで有効でグローバルスコープと言います。
関数の中にあるスコープはその関数内のみで有効でローカルスコープと言います。

###定数のスコープは？
[PHP: 定数 - Manual](https://www.php.net/manual/ja/language.constants.php)
> 定数のスコープはグローバルです。 つまり、スコープによらずスクリプトの中ではどこでも定数に アクセスできます。

##returnとは？

関数内でreturnと書くとその時点で値が戻されて、それ以降の処理は無視されます。

returnした時点で関数の呼び出し元に処理が戻り、結果として「関数内のそれ以降の処理」が実行されないということになります。returnは関数内でしか使えません。

**exitとの違い**
exitはその時点で処理を終了してそれ以降は実行しない。関数の中でも外でも使えます。

##無名関数
以下の関数は現在、3つの値を渡すと合計を返してくれる状態。
この関数を値として扱うことができるので、

```php
<?php

function sum($a, $b, $c) {
  return $a + $b + $c;
}
```
変数に代入します。

```php
$sum = function ($a, $b, $c) { //無名関数
  return $a + $b + $c;
};
```

何をしたか説明します。

```function sum($a, $b, $c) { // 変更前```

``` $sum = function ($a, $b, $c) { // 変更後```

名前はわかりやすく同じにします。
代入するのは処理そのものだけにしたいので
functionの後の名前は不要になります。
この時functionの後ろにスペースを開ける必要があるので注意してください。

```   return $a + $b + $c;
} // 変更前```

```   return $a + $b + $c;
}; // 変更後```

また、普通の関数は最後に;(セミコロン)は不要ですが、
このように値として代入する場合は必要です。

その上でこの関数を実行したい場合は、変数名に()を付けて引数を渡せばOKです。

```php
$sum = function ($a, $b, $c) { // 無名関数
  return $a + $b + $c;
};

echo $sum(100, 300, 500) . PHP_EOL; // 引数を渡して実行
```

この関数には名前がないので**無名関数**、もしくはクロージャーと呼びます。

上の関数とどちらを使っても結果は同じですが、無名関数を使えるようになると
関数自体を別の関数に引数にして渡すことができたりと便利になります。

##条件演算子
まずは、合計がマイナス値だったら0を返す
計算結果を変数に入れてあげて条件分岐する関数があるとします。

```php
function sum($a, $b, $c) 
{
  $total = $a + $b + $c; // 合計値を$totalに代入
  
  if ($total < 0) {
    return 0; // 0を返す
  }  else {
    return $total; // 計算結果を返す
  }
}

echo sum(100, 300, 500) . PHP_EOL; // 900
echo sum(-1000, 300, 500) . PHP_EOL; // 0
```

実行結果

```terminal
~ $ php main.php
900
0
```

この条件分岐を**条件演算子**でもっと短く書くことが出来ます。

```php
function sum($a, $b, $c) 
{
  $total = $a + $b + $c;
  
  // if ($total < 0) {
  //   return 0;
  // }  else {
  //   return $total;
  // }
  return $total < 0 ? 0 : $total; // 条件 ？ 値 ： 値
}

echo sum(100, 300, 500) . PHP_EOL;
echo sum(-1000, 300, 500) . PHP_EOL;
```

たった一行にすることができます。
[条件 ？ 値 ： 値] という記法で書きます。
trueだったら左の値、falseだったら右の値に条件分岐します。

条件演算子は短く書けますが、短所としては一見して見づらいという点があります。

##型付け
引数の型を指定する方法です。

```php
<?php

function showInfo(string $name, int $score): void
{
  echo $name . ':' . $score . PHP_EOL;
}
// このように名前とテストの点数を表示したかったとする
// showInfo('john', 40);
// しかし今回は以下のように予期しない引数を渡してしまったとする
showInfo('john', 'canada');
```
```function showInfo(string $name, int $score): void```
引数の前に型の名前をこのように指定すると、
文字列と整数値だけしか受け付けたくないという指定ができます。

なお、返り値の型も指定することができて：のあとに書けばOKです。

返り値がない場合はこのように**:void**という特殊なキーワードを使います。

それでは実行してみます。

```
Fatal error: Uncaught TypeError: 
Argument 2 passed to showInfo() must be of the type int
```

このようなエラーが出てintがくるべきところにstring、つまり文字列が来てしまっているというのがわかります。

###型付けには強弱がある
このような型指定はデフォルトでは**弱い型付け**という方式になっていて、
違った型でも可能な限り正しい型に変換してしまうという性質があります。

intの部分に文字列の'6'等を渡してもPHPが数値に変換して実行します。

もし変換してほしくない場合は強い型付けをする必要があります。
declare文を最初につけます。

```php
<?php

declare(strict_types=1); // 強い型付けを指定

function showInfo(string $name, int $score): void
{
  echo $name . ':' . $score . PHP_EOL;
}

showInfo('john', 'canada');
```
こちらを実行すると以下のようなエラーが出ます。

```terminal
Fatal error: Uncaught TypeError: Argument 2 pa
ssed to showInfo() must be of the type int, st
ring given,
```

Argument 2：2番目の引数
2番目の引数がintじゃないと言ってくれています。

###nullも一緒に渡せる

```php
function showInfo(?string $name, ?int $score): void
```
型付けの前に?をつけることでnullかstringかという意味になります。
条件分岐や引数の型につけることができます。
ただし、整数か文字列かのような指定はできません。
あくまでnullかそれ以外かという指定にしか使えません。

##配列

例えばゲームのスコアを管理したいとして、
最初のスコアが85点、次が30点、次が100点だったとします。

```php
<?php

$score1 = 85;
$score2 = 30;
$score3 = 100;
```
これらは同じ意味合いのデータなのでまとめて同じ名前で扱えたほうが便利になります。

```php
<?php

$scores = [85, 30, 100];
```

このように複数形のscoresという変数名にまとめることができます。
これを配列といいます。

また以下のような表記も可能です。

```php
$scores = [
  85,
  30,
  100,
];
```
このように改行を挟んでもOKで、最後に,を入れてもOKとなります。
こうすると全ての行が同じ形式になって追加や削除、入れ替えがしやすいです。

###それぞれの要素にアクセス

変数名に大括弧をつけて、その値が何番目かというインデックスを与えます。

```php
echo $scores[1] . PHP_EOL;
```
実行結果

```
~ $ php main.php
35
```

インデックスは0から始まるので35が表示されます。
与えたインデックスを添字と言います。

###値の変更
インデックスを使い代入すればOKです。

```php
$scores[1] = 60;
echo $scores[1] . PHP_EOL;
```
実行結果

```
~ $ php main.php
60
```

###配列のキーを指定
配列の中身を表示するにはvar_dump()か変数に関する情報を見せてくれる print_r() という命令を使います。

```php
<?php

$scores = [
  85,
  35,
  100,
];

var_dump($scores);
print_r($scores);
```

実行結果

```terminal
~ $ php main.php
array(3) {
  [0]=>
  int(85)
  [1]=>
  int(30)
  [2]=>
  int(100)
}

Array
(
    [0] => 85
    [1] => 35
    [2] => 100
)
```

値にアクセスするための 0 からの連番を好きな数値や文字列にすることができます。

```php
<?php

$scores = [
  'first'   => 85,
  'second'  => 30,
  'third'   => 100,
];

var_dump($scores);
print_r($scores);
```

実行結果

```
~ $ php main.php
array(3) {
  ["first"]=>
  int(85)
  ["second"]=>
  int(30)
  ["third"]=>
  int(100)
}
Array
(
    [first] => 85
    [second] => 30
    [third] => 100
)
```
これで連番がキーに変わっています。
'first' 'second' 'third' に当たる部分を**値に対するキー**と呼びます。

###個々の値にアクセス

```php
<?php

$scores = [
  'first'  => 85,
  'second' => 30,
  'third'  => 100,
];

echo $scores['third'] . PHP_EOL;
```

実行結果

```
~ $ php main.php
100
```

配列は**値とキーがセットになったデータ構造**で、
キーを指定しなければ 0 からの連番がキーになります。

###配列 array() と [] 

古い書き方が array() 新しい書き方が []
違いはありません。

[PHP: 配列 - Manual](https://www.php.net/manual/ja/language.types.array.php)
>PHP 5.4 以降では配列の短縮構文が追加され、 array() の代わりに [] を使えるようになりました。

##foreachで配列を操作する
as を使うことで配列のすべての要素に対して何らかの処理を行います。

```php
<?php

$scores = [
  'first'  => 85, 
  'second' => 30, 
  'third'  => 100,
];

foreach ($scores as $score) {
  echo $score . PHP_EOL;
}
```

個々のスコアという意味で単数形のscoreと付けました。
$scoreの部分の変数名は好きに付けられます。

実行結果

```
~ $ php main.php
85
30
100
```

\$scores から値を一個ずつ取り出して $score に代入してから、処理を実行してくれます。

##キーも合わせて表示する場合

```php
<?php

$scores = [
  'first'  => 85, 
  'second' => 30, 
  'third'  => 100,
];

foreach ($scores as $key => $score) {
  echo $key . ' - ' . $score . PHP_EOL;
}
```

```foreach ($scores as $key => $score)```
このキーの変数名に \$key が入ってきます。


```echo $key . ' - ' . $score . PHP_EOL;```
\$score と合わせて以下のように表示します。

```
~ $ php main.php
first - 85
second - 30
third - 100
```

配列とforeachはよく合わせて使うことがあります。

##配列の要素を展開する
別の配列で管理していた値を途中に入れ込みたい場合の説明をします。

数値だけでなく別のデータ値(文字列)や配列も入れることができます。
...を付けると配列の中身が入れ込まれます。
配列の中に配列を入れたり、別のデータ値を入れることもできます。

```php
<?php

$moreScores = [
  48,
  71,
  'excellent',
  [55, 29, 84]
];

$scores = [
  85,
  30,
  ...$moreScores, // 配列の中身が入れ込まれる
  100,
];

print_r($scores);
```

実行結果

```
~ $ php main.php
Array
(
    [0] => 85
    [1] => 30
    [2] => 48
    [3] => 71
    [4] => excellent
    [5] => Array
        (
            [0] => 55
            [1] => 29
            [2] => 84
        )

    [6] => 100
)
```

###84にアクセスしたい場合は？
配列の5番目の中の2番目の要素になるので、

```echo $scores[5][2] . PHP_EOL;```

これでアクセスできます。


##可変長引数

(...仮引数)にすると渡された全ての引数を配列にして、代入してくれます。
このような引数を**可変長引数**と言います。

```php
<?php

function sum(...$numbers) // 可変長引数
{
  $total = 0;
  foreach ($numbers as $number) {
    $total += $number;
  }
  return $total;
}
echo sum(1, 3, 5) . PHP_EOL;
echo sum(4, 2, 5, 1) . PHP_EOL;
```

実行結果

```
~ $ php main.php
9
12
```

順に説明をします。

```php
function sum(...$numbers)
```

これが可変長引数です。関数の引数が何個きても合計を出すことができます。

```php
$total = 0;
```
ここで合計を初期化します。

```php
foreach ($numbers as $number) { 
```
それぞれの要素を$numberで取り出します。

```php
$total += $number;
```
$totalに足していきます。

```php
return $total;
```
合計値が返されます。

##複数の返り値を受け取る方法
配列を返り値にすることもできます。
合計だけでなく平均も返すようにして、配列を作ります。

```php
<?php

function getStats(...$numbers)
{
  $total = 0;
  foreach ($numbers as $number) {
    $total += $number;
  }
  return [$total, $total / count($numbers)];
}

print_r(getStats(3, 5, 7));
```

  ```return [$total, $total / count($numbers)];```
返り値は配列で１つ目の要素が\$total ２つ目の要素を平均にしたいので
２つ目はこのように\$totalを$numbersの個数で割ります。

###count
配列の個数を求めるためにcount()を使っています。
>
count — 変数に含まれるすべての要素、 あるいはオブジェクトに含まれる何かの数を数える
https://www.php.net/manual/ja/function.count.php

実行結果

```
~ $ php main.php
Array
(
    [0] => 15
    [1] => 5
)
```
合計と平均が出ています。

###それぞれの値を変数に一気に代入する方法

```php
list($sum, $average) = getStats(1, 3, 5);
```
もしくは

```php
[$sum, $average] = getStats(1, 3, 5);
```
上記どちらかでそれぞれの値を変数に一気に代入できます。
実際にやってみます。

```php
<?php

function getStats(...$numbers)
{
  $total = 0;
  foreach ($numbers as $number) {
    $total += $number;
  }
  return [$total, $total / count($numbers)];
}

[$sum, $average] = getStats(3, 5, 7);

echo $sum . PHP_EOL;
echo $average . PHP_EOL;
```

実行結果

```
~ $ php main.php
15
5
~ $ 
```

これで配列を使い複数の返り値を受ける方法がわかりました。

これでPHP基礎文法は終わりです。

##Links

*PHP: 言語リファレンス - Manual - PHP.net*
*https://www.php.net/manual/ja/langref.php*

*ドットインストール 詳解PHP 基礎文法編*
*https://dotinstall.com/lessons/basic_php_grammer*

*PHPの「define」と「const」の違い*
*https://qiita.com/schrosis/items/485b984e05b2eb4521b4*

---
Twitterでも毎日プログラミングについて投稿してます。
よかったらフォローお願いします:blush:
https://twitter.com/DawaProgramming