PHP
初心者
入門
新人プログラマ応援
More than 1 year has passed since last update.

前書き

筆者自体PHP初心者ですが、コメント欄と併用してしっかりとした基礎をまとめているシートにできると思いますので、玄人の方は、間違っていたらコメント欄へご指摘願います。

自己紹介

Twitter @konojunya

じゅんじゅんというニックネームで、関西を拠点に活動しているフロントエンドエンジニアです。

HAL大阪の新2回生です👍 (2016.4.18現在)

よくstart up系イベントに行くので、大阪らへんの方は会いましょう!

では、早速。

初めてのPHP

順番にPHPを攻略していきたいと思います。

環境

筆者はPHP v5.5でやっています。
phpをインストールして、Webサーバ(Apacheなど)にあげれば動きます。
ローカル開発環境は
vagrantを用いたPHPの環境構築

などをご覧ください。

PHPは、.phpファイルに

index.php
<?php

//insert code...

?>

で、書くことができます。

早速PHPに入っていきたいと思います。

変数

PHPでは、型の宣言がなくJavaScriptのようなvarもありません。(フレームワークとかは知らん!!)

最初に$をつけて変数を宣言します。

index.php
$msg = "Hello World";
echo $msg;

$msgという変数に、文字列の"Hello World"を代入した形です。

echoを使う事で、変数を展開してWEBページへ出力してくれます。

この時の$msgの型はString型ですね。

PHPが扱う型には以下のようなものがあります

  • 文字列を扱う
    • string
  • 数値を扱う
    • int
    • float
  • 真偽値(true / false)
    • boolean
  • 配列
  • オブジェクト
  • null(何もない)

型などはvar_dumpなどを用いて簡単に確認できます

index.php
$msg = "Hello World";
var_dump($msg);

定数

先ほどの変数は、後からでも変更可能な箱でした。

定数は、一度定義すると後から変えることのできないものになっています。

定数を定義するときはdefineというキーワードを使います。

index.php
define("PI",3.141592);

echo PI;

この時に注意したいのが、$いらないということと

定数を定義するときは全部大文字にするのが、デファクトスタンダードだということです。

このPIは定数なので、後から

index.php
PI = 3;

のようなゆとり教育は許さないということです。

なお、定数には幾つか最初から定義されているものがあります。

index.php
var_dump(__LINE__); //今の行数
var_dump(__FILE__); //そのファイルまでのパス
var_dump(__DIR__);  //ディレクトリのパス

文字列

文字列は"ダブルクォーテーション"'シングルクォーテーション'で囲むことで、扱うことができます。

この差は、そのクォーテーションの中で、変数が展開できるか否かです。

index.php
$name = "konojunya";

echo "My name is $name";

こうすることで、ダブルクォーテーションの中で、変数を展開できます。

なお、変数の展開は、もっとわかりやすく書くこともできます。

index.php
$name = "konojunya";

echo "My name is $name";
echo "My name is ${name}";
echo "My name is {$name}";

これはすべて同じ出力結果になります。

では、シングルじゃないとダメな時どうするのか。

文字列の連結

変数を展開したものと、文字列を連結させれば、同じことができます。

index.php
$name = "konojunya";

echo 'My name is '.$name;

PHPでは.(ドット) を使うことで、連結ができます。

配列

似たようなデータを一つの名前で管理したい時に使えるのが、配列です。

index.php
$colors = array("red","blue","yellow");

PHP5.4以上なら、[]で置き換えることができます。

index.php
$colors = ["red","blue","yellow"];

この場合、例えばredを出したい場合

index.php
echo $colors[0];

先頭から、0..1..2..3..と続いているので、redは0番目。

大カッコに添字で、取り出せます。

これでは、データを取り出しにくいので、先人は名前をつける機能をつけてくれました。

連想配列

書き方を見てみましょう

index.php
$members = [
  "jun" => "konojunya",
  "hoge" => "hogehogeo"
];

取り出し方も簡単になっています。

index.php
echo $members["jun"]; //konojunya

ループ&条件分岐

ループ(for,while)と条件分岐(if,switch)は、他の言語と変わらないので省きます。

PHPでは、HTMLに埋め込むことがよくあると思います。

そこで

index.php
?><ul>
  <?php for($i=0;$i<10;$i++){ ?>
  <li><?php echo $i ?></li>
  <?php } ?>
</ul>

と書くのは、見づらいので、コロン構文というものを使い書き換えることができます。

index.php
?><ul>
  <?php for($i=0;$i<10;$i++): ?>
  <li><?php echo $i ?></li>
  <?php endfor; ?>
</ul>

初めの波カッコを:に変えて、終わりの波カッコをend〇〇に置き換えることができます。

関数

関数は、複数の処理を一つにまとめてくれるものです。

関数は、引数戻り値が存在します。

まず単純にHello Worldechoするhello関数を作りましょう

index.php
function hello(){
  echo "Hello World";
}

hello(); //Hello World

その他の言語と同じですね。functionを使って、関数を定義します。

では、名前を引数にとった場合どうなるか。

index.php
function hello($name){
  echo "Hello ${name}";
}

hello("junya"); // Hello junya

junya$nameに代入して、使っています。

なお、この$nameはこのhello関数の中だけで使えるローカル変数になります。

この関数の外から$nameにアクセスはできません。

戻り値を使った場合はどうなるでしょうか。

index.php
function hello($name){
  return "Hello ${name}";
}

echo hello("junya"); // Hello junya

returnというキーワードで、その関数から値を返すことができます。

クラス

クラスというのは、設計図とよく言われています。

何回も同じようなものが登場する場合は、このクラスを使った方が良いとされています。

書き方を見てみましょう。

では、ユーザーを管理するUserクラスを作りましょう。

index.php
class User{
  //property
  public $name;

  //constructor
  public function __construct($name){
    $this->name = $name;
  }

  //method
  public function sayName(){
    echo "Hello $this->name !";
  }
}

クラス名は最初が大文字という決まりがあるので注意しましょう。

クラスは、propertyconstructormethodを持ちます。

propertyは、そのクラスが持つ値です。
constructorは、そのクラスがインスタンス化される時に絶対呼ばれるものです。
methodは、そのクラスが持っている関数だと思ってください。

このUserクラスは、$nameというプロパティを持っています。

インスタンスする際に、constructorによってその$nameに引数で入ってきたものが代入されます。

インスタンスするには、newというキーワードを使います。

index.php
$junya = new User("junya");

これで、$junyaは、自分の名前や、sayName()が使えます。

自分の名前にアクセスするには

index.php
echo $junya->name;

sayNameを使えば

index.php
$junya->sayName();

という風に使えます。

クラスの継承

クラスを作る際に、さっきのクラスに似てるけどここで差別化してるし、、

ちょっと違う挙動をさせたい。。

みたいなものがあったとして、そのクラスをまた1から書くのはあまり、よろしくないです。

そんな時に、前作ったクラスを引き継いで新しいものを作るクラスの継承が便利でしょう。

さっき作ったUserクラスを継承させて、SpecialUserというクラスを作ります。

index.php
class User {
  public $name;

  public function __construct($name){
    $this->name = $name;
  }

  public function sayHi(){
    echo "Hello $this->name !";
  }
}

class SpecialUser extends User {
  public function saySpecialHi(){
    echo "I am Special $this->name";
  }
}

SpecialUserクラスを作るのに、Userクラスを継承するには、

extendsを使います。

これで、SpecialUserクラスは独自のメソッドも使えますが、Userクラスのものも使えます。

SpecialUserをインスタンスする際も

index.php
$junya = new SpecialUser("junya");

で、大丈夫です。

この時できたSpecialUserはUserを継承しているので、

SpecialUserが子クラス。Userが親クラスと言います。

over ride

ここで、UserクラスにあるsayHiメソッドをSpecialUserクラスでも書くとどうなるのでしょうか。

index.php
class User {
  public $name;

  public function __construct($name){
    $this->name = $name;
  }

  public function sayHi(){
    echo "Hello $this->name !";
  }
}

class SpecialUser extends User {
  public function sayHi(){
    echo "I am Special $this->name";
  }
}

このようにすると

index.php
$junya = User("junya"); //Userクラス
$kono = SpecialUser("kono"); //SPUserクラス

$junya->sayHi(); // Hello junya
$kono->sayHi(); // I am Special kono

同じメソッドなのに、スペシャルなkonoくんとパンピなjunyaでは挙動が違います。

これをover rideと言います。

単純に「上書き」です。

このover ride便利ですが、して欲しくない場合もあると思います。

この時に使えるのがfinalというキーワードです。

さっきのUserクラスのsayHiをfinalを使って、over rideできないようにしましょう。

index.php
class User {
  public $name;

  public function __construct($name){
    $this->name = $name;
  }

  final public function sayHi(){
    echo "Hello $this->name !";
  }
}

class SpecialUser extends User {
  public function sayHi(){
    echo "I am Special $this->name";
  }
}

Userクラスにfinalをつけることで、SpecialUserのsayHiメソッドはover rideに失敗するので、

エラーになると思います。

そろそろアクセス権を見ていきたい時期ですね。

アクセス権

今まで、クラスの中に出てくるpublicですね。これがアクセス権です。

アクセス権には次の3つがあります。

  1. public
  2. protected
  3. private
  • public

publicは、全域からアクセスが可能

  • protected

protectedは、親子クラスとクラス内からのみアクセス可能

  • private

privateは、クラス内からのみアクセス可能

に、なっています。

index.php
class User {
  public $name;

  public function __construct($name){
    $this->name = $name;
  }

  public function sayHi(){
    echo "Hello $this->name !";
  }
}

class SpecialUser extends User {
  public function sayHi(){
    echo "I am Special $this->name";
  }
}

この状態では、Userクラスの$nameはpublicで宣言しているため

インスタンス化した$junyaからも$junya->nameでアクセスできました。

これを

index.php
class User {
  private $name;

  public function __construct($name){
    $this->name = $name;
  }

  public function sayHi(){
    echo "Hello $this->name !";
  }
}

class SpecialUser extends User {
  public function sayHi(){
    echo "I am Special $this->name";
  }
}

privateにすると、クラス内からはアクセスできますが、そのほかからはアクセスできないので、

SpecialUserの$this->nameもアクセスできませんし、$junya->nameもアクセスできません。

SpecialUserは許可したい、、、、時は、privateをprotectedにしましょう!

staticについて

staticは、クラスをインスタンス化しなくても、使えるようにする仕組みです。

index.php
class User {
  public $name;
  public static $count = 0;
  public function __construct($name){
    $this->name = $name;
    self::$count++;
  }
  public static function getMes(){
    echo "Hello from static!";
  }
}

User::getMes();
$tom = new User("tom");
echo User::$count; //1

staticをつけたメソッドやプロパティはそのクラス名::メソッドなどでアクセスできます。

Userクラスの中で、自分自身を参照したい場合。

その時はselfを使って、self::$countのように使っていますね。

抽象クラス

index.php
abstract class BaseUser{ //抽象クラス
  public $name;
  abstract public function sayHi();
}

class User extends BaseUser{
  public function sayHi(){
    echo "Hello";
  }
}

宣言する際にabstractというキーワードをつけてあげます。

抽象クラスは、それ自体をインスタンス化することはできません。

抽象クラスのメソッドは、その拡張クラスに実装しないといけないという決まりをもたせることができます。

実装してない場合、エラーになります。

アクセス権なども、抽象クラスに合わせないといけません。

interface

さて、抽象クラスと似ているものにinterfaceというものがあります。

index.php
interface sayHi {
  public function sayHi(); //interfaceは絶対public
}
interface sayHello{
  public function sayHello();
}

class User implements sayHi,sayHello {
  public function sayHi(){
    echo "Hi!";
  }
  public function sayHello(){
    echo "hello";
  }
}

classは、大きくそのものの設計図なのに対して、interfaceはもっと細かい部品部品で見たものという認識をしています。(間違っていたらコメントください。)

interfaceで宣言したものも、クラスの中で実装していかないといけません。

ですが、今までのextendsではなく、implementsというものを使います。

ここで、大きな違いが、抽象クラスは1つだけど、interfaceは複数同時に追加できるという点です。

なので、より細かい部品(歩く、話す)を作るのにはinterfaceを使い、大部分(人間、生物、車など)を定義するのにクラスを使うのかなぁという具合です。

外部ファイルの読み込み

では、そろそろ長くなりすぎていませんか?

ファイルを分けて見やすくしていきましょう。

新しく、functions.phpを作ります。

functions.phpには以下の内容があるとします。

functions.php
function hello(){
  echo "Hello";
}

.......

関数を定義しているfunctions.phpindex.phpで読み込みましょう。

index.php
require "functions.php"; // どれか
require_once "functions.php";
include "functions.php";
include_once "functions.php";

この4つでファイルの読み込みができます。

requireとincludeの違いは、

requireは、ファイル名が違うかったりするとエラーが出ます。

includeは、無視してそのまま進みます。

???_onceは、一度読み込んでいればスルー。読んでいなければ読み込むものです。

index.php
require "functions.php";

hello();

ライブラリなどもこの方法で、読み込むことができますね。

では、自分の作ったものと他人の作ったものの名前が同じ場合どうすればいいでしょうか。

名前空間

それを解決してくれるのが、名前空間です。

まずは、使ってみましょう。

functions.phpの最初に

functions.php
namespace junya\functions;

function hello(){
  echo "Hello";
}

のように書きます。

注意しなければならないのが、名前空間の宣言は一番最初にしないといけません。

これをindex.phpで使ってみましょう

index.php
// use konojunya\functions as func;
// use konojunya\functions

useを使うことで、その名前空間を使うことができます。

なお、 use konojunya\functions as funcはkonojunya\functionsにfuncという名前をつけてこの中では使うよというものです。

use konojunya\functionsだと、一番最後のfunctionsを取ってくれます。

この名前空間をどう使うのか。

index.php
require "functions.php";
use konojunya\functions as func;

func\hello();

このように、その関数の最初に、useで指定した文字をつけます。

これで、ライブラリなどとの衝突を避けることができます。

例外処理

そろそろ終盤です。

最後に、例外の処理方法について、まとめたいと思います。

例えば、割り算をするdivision()という関数を作りたいと思います。

index.php
function division($num1,$num2){
  return $num1 / $num2;
}

echo division(4,2); // 2

この関数の弱点は、$num2に0が入った場合です。

学校では

index.php
function division($num1,$num2){
  if($num2 === 0){
    return "2つ目に0は指定できません。";
  }else{
    return $num1 / $num2;
  }
}

こんな風にして、まず0が来たらifで弾く。みたいな感じです。

これは、例外処理の書き方で次のように書き直せます。

index.php
function division($num1,$num2){
  try {
    if($b === 0){
      throw new Exception("can not use 0");
    }
    return $num1 / $num2;
  } catch (Exception $e) {
    return $e->getMessage();
  }
}

throwで Exceptionというクラスをインスタンス化したものをcatchに投げているという感じです。

Exceptionは、クラスなので、catchの方で、$eというのに格納してあげます。

そのあと、getMessage()というメソッドを使うことで、Exceptionをインスタンスするときに、引数に入れた値を取得することができます。

これで、例外処理が来た場合でも、ただのエラーではなく、自分で作ったものに変えることができました。

あとがき

まだまだPHPは奥が深いですが、基礎の基礎の基礎ということで、今回抑えていきました。

説明が間違えている!などあれば、コメント欄で指摘してください。

至急、これはQiitaの記事を書き変えないと、間違った情報になってしまう!というのがあれば、

Twitter @konojunya へご連絡くだされば、幸いです。。

ホームページ hello world

ありがとうございました!