20200623のPHPに関する記事は9件です。

Vdebugを使ってVimでPHPのデバッグ環境を整える

PHPはずっとPHPStormで書いていて不自由はなかったのですが、最近他の言語でvimを使いだしたところ、全部vimでやりたくなる一過性の病にかかったのでPHPでデバッグ環境を整えています。

PHPのxdebugを実行するのにvimのプラグインVdebugを使います。
vim-vdebug/vdebug: Multi-language DBGP debugger client for Vim (PHP, Python, Perl, Ruby, etc.)

全部マニュアルに書いてあるので読めば終了なんですが、せっかく触りながらマニュアルの内容を確かめたので備忘として残しておきます。
ただし、CLIでローカル実行した場合についてです。
ブラウザからのリクエストで起動する場合やリモートデバッグはまたいつか追記するかもしれません。

<実行中の雰囲気>
phpdbg-memory-2.gif

インストール・初期設定

xdebugのインストールはすでにたくさん記事があるので省略。

Vdebugのインストール

僕はPlugin managerにjunegunn/vim-plugを使っています。

.vimrc
call plug#begin('~/.vim/plugged')
" Debug
Plug 'vim-vdebug/vdebug'

call plug#end()

.vimrcに追記してから

:PlugInstall

呼び出しスクリプトの作成

また、CLIから実行する場合は、環境変数XDEBUG_CONFIGidekeyの指定が必要です。毎回打つのが面倒なのでショートカット用のshellscriptを作ります。

php-xdebug
#!/bin/bash
export XDEBUG_CONFIG="idekey=xdebug"
/usr/bin/php "$@"

phpのパスは環境に合わせます。
実行権限付与して適宜パスの通っている場所に移します。

$ chmod +x php-xdebug
$ mv php-xdebug /to/your/path/

こんな風に使用。

$ php-xdebug myscript.php

使い方

基本の使い方

  1. 止めたい行にブレークポイントを設置(F10)
  2. Debuggerをスタート(F5)
  3. Terminal別タブでそのブレークポイントを通過する処理を呼び出し
  4. Debuggerをストップ(F6を2回)

windowの見方

各windowはこんな感じになります。
スクリーンショット 2020-06-13 23.02.54.png

よく使うキーバインド

  • F5・・Start
  • F6・・Stop
  • F2・・Step Over
  • F3・・Step In
  • F4・・Step Out
  • F9・・Run To Cursor
  • F10・・Toggle Break Point

ブレークポイント

  • F10でtoggle
  • :BreakpointWindowでブレークポイント一覧を確認
    • このウィンドウで消したいブレークポイントの行にカーソルをあわせて dd で該当ブレークポイントを削除
  • :BreakpointRemove * で一括削除

いろんなブレークポイント

F10の通常の行ブレークポイント以外にいくつかの特性を持ったブレークポイントを利用できます。

使い方
:Breakpoint <type> <arguments>

conditional

行ブレークポイントと似ていますが、ブレークが発動する条件を指定できます。
使い所は「ループの◯回目のみ止めたい」とかですかね。
標準の行ブレークポイント以外では唯一これだけ使いそうな気がします。

例)$xが2の場合のみブレーク
:Breakpoint conditional $x == 2

exception

指定した例外が発生した場合にブレークする

:Breakpoint exception PDOException

call

指定の関数が呼び出された場合にブレークする。マニュアルを見るに、挙動は保証されていないようです。

:Breakpoint call open_file

return

指定の関数からreturnされた場合にブレークする。同じく、挙動は保証されていないようです。

:Breakpoint return open_file

watch

指定の変数に書き込みがあった場合にブレークする。マニュアルにはxdebugでサポートされていないので期待するなと書いてあります。僕の環境では動かなかったです。特に期待してなかったので大丈夫でした。

:Breakpoint watch $myvar

任意の式の評価

実行ポイントのコンテキストで任意の式を評価させることができます。デバッガーの醍醐味とも言える機能ですね。
実行方法が3種類あります。

1) 記述した式を評価する方法

:VdebugEval $x * 3

これはwatch windowに表示されますが、ステップを進めるとデフォルトのwatch windowに戻ります。
指定した式の評価をwatch windowに固定表示させたい場合は:VdebugEval!を使います。

:VdebugEval! $x * 3

デフォルトのwatch windowに戻したい場合は式無しで以下を打ち込みます

:VdebugEval!

2)visualモードで選択した式を評価する方法

v で選択後 <leader>e で評価

3) traceウィンドウで評価を確認する

:VdebugTraceを使うとwatch windowとは別にtrace windowで式をトレースできます。
VdebugEval!と似ていますが、watch windowをデフォルトとのままにしつつ式の評価を追うことができます。

:VdebugTrace $x

細かい設定とか

デフォルトオプション

    let g:vdebug_options = {
    \    'port' : 9000,
    \    'timeout' : 20,
    \    'server' : '',
    \    'on_close' : 'stop',
    \    'break_on_open' : 1,
    \    'ide_key' : '',
    \    'debug_window_level' : 0,
    \    'debug_file_level' : 0,
    \    'debug_file' : '',
    \    'path_maps' : {},
    \    'watch_window_style' : 'expanded',
    \    'marker_default' : '⬦',
    \    'marker_closed_tree' : '▸',
    \    'marker_open_tree' : '▾',
    \    'sign_breakpoint' : '▷',
    \    'sign_current' : '▶',
    \    'continuous_mode'  : 1,
    \    'simplified_status': 1,
    \    'layout': 'vertical',
    \}

個別で上書き

.vimrc
    if !exists('g:vdebug_options')
      let g:vdebug_options = {}
    endif
    let g:vdebug_options.port = 9001

まとめて上書き

.vimrc
let g:vdebug_options = {
    \   '"port' : 9000,
    \    'break_on_open' : 0,
    \    'ide_key' : '',
    \}

基本はデフォルトのまま使っていますが、break_on_openは0にしています。これは実行されるスクリプトの1行目でステップが止まるかどうかの指定です。ブレークポイントより前で止まっても鬱陶しいのでオフにしています。

レイアウト

g:vdebug_options.layouthorizontalを指定するとレイアウトがデフォルトから変わります。
スクリーンショット 2020-06-23 21.46.34.png

感想

  • evaluationを複数同時にtraceできない点以外はIDEの場合とくらべて特に不便とかはなかったです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP基礎<PHPの書き方・表示方法>

前書き

PHPを基礎から学習しています。
積み重ねのアウトプットとして更新していきます。

PHPの書き方

index.php
<?php // 開始タグ
   echo ('cat');    
   echo ('<br>'); //改行
   echo ('こんにちは');  // プログラム
   echo (123);
?> // 終了タグ

  • 開始タグ<?phpと終了タグ?>を書き、その間にプログラムを記述する
  • PHP ファイルの拡張子は .php とする
  • '○○'シングルクオーテーションは必ず必要
  • echoの場合は(  )が無くても可
  • ; (セミコロン)は必ず付ける
  • コメントアウトは//から改行までか/* から */の範囲に記述する

ブラウザにPHPを表示する

  • MAMPを使ってPHPを表示する

http://localhost:8888/(PHPプロジェクトのフォルダ名)/(PHPファイル名).php
と入力すればブラウザで表示が確認ができる。

あとがき

初回は基本の書き方のみまとめました。
次回は変数について、初心者の勉強のまとめをしていきたいと思います!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メディアクエリの使い方

メディアクエリの使い方

個人アプリでレスポンシブ対応が必要だったので、その使い方を記事にまとめました。

index.blade.php
<div class = "content">
    @foreach($posts as $post)
      <img src="/storage/{{$post->image}}" class="image" width=293px height=293px>
    @endforeach
  </div>
index.css
@media (max-width: 1420px) {
  .content {
    margin: 90px 218px 0;
  }
 }

 @media (max-width: 1420px) {
  .image {
    width: 280px;
    height: 280px;
  }
 }

 @media (max-width: 1340px) {
  .content {
    margin: 90px 200px 0;
  }
 }

 @media (max-width: 1340px) {
  .image {
    width: 260px;
    height: 260px;
  }
 }

 @media (max-width: 1260px) {
  .content {
    margin: 90px 180px 0;
  }
 }

 @media (max-width: 1260px) {
  .image {
    width: 240px;
    height: 240px;
  }
 }

こんな感じで要素の幅によって中身のサイズを調整してあげる。
検証機能を使えば、幅が簡単にわかるので、それを見ながら調整していけば、
自然にビューのレスポンシブができるようになります!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel環境構築時のエラー解決 Mac

エラー内容

$ composer global require laravel/installer

Changed current directory to /Users/ooshiroippei/.composer
Using version ^3.1 for laravel/installer
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for laravel/installer ^3.1 -> satisfiable by laravel/installer[v3.1.0].
    - laravel/installer v3.1.0 requires ext-zip * -> the requested PHP extension zip is missing from your system.


Installation failed, deleting ./composer.json.

ext-zipが必要

重要なエラー箇所を和訳すると、
「laravel/installer v3.1.0にはext-zipが必要です。リクエストされたPHP拡張zipがシステムにありません」と書かれている。

原因

Macに最初から入っているPHPにはzipのサポート機能がないためエラーが起こっていた。

解決策

これは改めてPHPを入れ直すことで解決できる。

①MacにPHPを再インストールするには「Homebrew」を使う。
こちらを参考。
https://awesome-linus.com/2019/08/17/mac-homebrew-install/

②PHPをインストールする

//HomeBrewのバージョン確認まで終わったらインストール
$ brew install php

//zipがサポートされているか確認
$ php --ri zip

//Laravelインストール
$composer global require laravel/installer

各エラー対策

Extension 'zip' not present.とエラーが出た場合

$ brew link php

brew link phpでエラー

Linking /usr/local/Cellar/php/7.4.7...
Error: Could not symlink sbin/php-fpm
/usr/local/sbin is not writable.

$brew doctor

Warning: The following directories do not exist:
/usr/local/Frameworks
/usr/local/sbin

You should create these directories and change their ownership to your account.
  sudo mkdir -p /usr/local/Frameworks /usr/local/sbin //実行
  sudo chown -R $(whoami) /usr/local/Frameworks /usr/local/sbin //実行

Warning: You have unlinked kegs in your Cellar.
Leaving kegs unlinked can lead to build-trouble and cause brews that depend on
those kegs to fail to run properly once built. Run `brew link` on these:
  php

Warning: /usr/bin occurs before /usr/local/bin
This means that system-provided programs will be used instead of those
provided by Homebrew. The following tools exist at both paths:

Consider setting your PATH so that /usr/local/bin
occurs before /usr/bin. Here is a one-liner:
  echo 'export PATH="/usr/local/bin:$PATH"' >> /Users/user/.bash_profile 
  rake
  bundle
  tidy
  sqlite3
  bundler
  rails

//各エラー項目に出ているコマンドを実行していく。

$sudo mkdir -p /usr/local/Frameworks /usr/local/sbin
$sudo chown -R $(whoami) /usr/local/Frameworks /usr/local/sbin
$echo 'export PATH="/usr/local/sbin:$PATH"' >> /Users/user/.bash_profile
//パスを通したあとは必ずsourceで際読み込み
$source ~/.bash_profile

//バージョンを確認
$php -v

//zipを確認
$ php --ri zip

zip

Zip => enabled
Zip version => 1.15.6
Libzip headers version => 1.7.0
Libzip library version => 1.7.1

//Laravelインストール
$composer global require laravel/installer
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPコールバック入門

コールバック

PHPの要素で関数として呼び出すことができるものをコールバック(またはCallable)といいます。

参考:PHP: コールバック / Callable - Manual

Examples

例1

PHP
function hello() {
    echo 'こんにちは。';
}

echo is_callable('hello') . PHP_EOL;

call_user_func('hello');
result
1
こんにちは。

is_callable — 引数が、関数としてコール可能な構造であるかどうかを調べる

PHP: is_callable - Manual


call_user_func — 最初の引数で指定したコールバック関数をコールする

PHP: call_user_func - Manual

例2

PHP
function hello() {
    echo 'こんにちは。';
}

call_user_func(hello);
result
PHP Warning:  Use of undefined constant hello - assumed 'hello' (this will throw an Error in a future version of PHP) in ...

PHP 関数はその名前を単に文字列として渡します。

PHP: コールバック / Callable - Manual

例3

PHP
function sum($int1, $int2) {
    return $int1 + $int2;
}

echo is_callable('sum') . PHP_EOL;

echo call_user_func_array('sum', [2, 5]);
result
1
7

call_user_func_array — パラメータの配列を指定してコールバック関数をコールする

PHP: call_user_func_array - Manual

例4

PHP
$hello = function () {
  echo 'こんにちは。';  
};

echo is_callable($hello) . PHP_EOL;

call_user_func($hello);
result
1
こんにちは。

一般的なユーザー定義関数とは異なり、 無名関数 もパラメータとして渡せます。

PHP: コールバック / Callable - Manual

ちなみに・・
PHP
$hello = function () {
  echo 'こんにちは。';  
};

var_dump($hello);
result
object(Closure)#1 (0) {
}

無名関数はPHPが用意しているClosureという特別なクラスのインスタンスとして実現されています。

無名関数の実装には Closure クラスを使っています。

PHP: 無名関数 - Manual


例5

PHP
class Player {
    private $name;

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

    public function getname() {
        return $this->name;
    }
}

$ichiro = new Player('イチロー');

echo is_callable([$ichiro, 'getname']) . PHP_EOL;

echo call_user_func([$ichiro, 'getname']);
result
1
イチロー

オブジェクトのインスタンスを渡すには配列を使います。 配列の 0 番目の要素にオブジェクトを、 そして 1 番目の要素にメソッド名を指定します。

PHP: コールバック / Callable - Manual

例6

PHP
class Car {
    public static function honk() {
        echo 'ビッビー';
    }
}

echo is_callable(['Car', 'honk']) . PHP_EOL;

call_user_func(['Car', 'honk']);
result
1
ビッビー

静的なクラスメソッドの場合、オブジェクトのインスタンスは不要です。 0 番目の要素として、オブジェクトのかわりにクラス名を指定します。

PHP: コールバック / Callable - Manual

例7

PHP
class Car {
    public static function honk() {
        echo 'ビッビー';
    }
}

echo is_callable('Car::honk') . PHP_EOL;

call_user_func('Car::honk');
result
1
ビッビー

PHP 5.2.3 以降では、 'ClassName::methodName' 形式で指定することもできます。

PHP: コールバック / Callable - Manual

おしまい

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPコールバック関数入門

Callable

PHPの要素で関数として呼び出すことができるものをコールバックまたは callable といいます。

参考:PHP: コールバック / Callable - Manual

本記事のタイトルにもあるとおり、コールバック関数といわれることもあるようです(実際 PHP マニュアルにも書かれています)。

無用な混乱をさけるため、本記事では呼び方を callable で統一することにします。

Examples

説明を読んだだけでは理解できないと思いますので、callable の例をたくさんみていくことにしましょう。

例1

PHP
function hello() {
    echo 'こんにちは。';
}

echo is_callable('hello') . PHP_EOL;

call_user_func('hello');
result
1
こんにちは。

5行目のis_callableは、引数が callable であるかどうかを調べてくれる関数です。

is_callable — 引数が、関数としてコール可能な構造であるかどうかを調べる

PHP: is_callable - Manual

引数が callable ならtrueを、 そうでなければfalseを返します。
また、echo true1を出力しecho falseは何も出力しません。

上記の例では1が出力されていますので、is_callbleの引数である文字列hellocallable であることがわかりました。
callable であるということは、文字列helloを関数として呼び出せるということです。

実際に、7行目でcall_user_funcという関数をつかって callable である文字列helloを関数として呼び出しています。

call_user_func — 最初の引数で指定したコールバック関数をコールする

PHP: call_user_func - Manual

こんにちは。と出力されていますので、1〜3行目で定義されている関数helloが呼び出されたことがわかりますね。

一般に、関数fooが定義されているとき文字列foocallable となります。
このとき文字列foocall_user_funcにわたすことによって、関数fooを呼び出すことができます。

例2

PHP
function hello() {
    echo 'こんにちは。';
}

is_callable(hello);

call_user_func(hello);
PHP Warning:  Use of undefined constant hello - assumed 'hello' (this will throw an Error in a future version of PHP) in ...
PHP Warning:  Use of undefined constant hello - assumed 'hello' (this will throw an Error in a future version of PHP) in ...

今回はエラーが出てしまいました。

エラーメッセージをよく読むとUse of undefined constant hello - assumed 'hello'と書かれています。
これは「定義されていない定数helloをつかっているようだけど、それは文字列helloのことじゃないか?」という意味です。

例1の5行目と7行目では、helloを二つのシングルクォーテーション('')でかこむことによって、それが文字列であることを表していました。

今回の例では、シングルクォーテーションでかこむことをしなかったため、helloは定数として解釈されます。
このとき PHP は定数helloの値を関数にわたそうとします。
ところが定数helloは定義されていませんので、PHP はたいへん狼狽し、エラーメッセージを吐き、森へ帰ってしまったというわけです(?)。

PHP 関数はその名前を単に文字列として渡します。

PHP: コールバック / Callable - Manual

例3

PHP
function sum($int1, $int2) {
    return $int1 + $int2;
}

echo is_callable('sum') . PHP_EOL;

echo call_user_func_array('sum', [2, 5]);
result
1
7

1〜3行目で定義されている関数sumは、二つの数値をうけとって、それらの和を返すというものです。

これを実行するためにはsum(2, 5)のように二つの引数を指定する必要があります。

このような場合でも、文字列sum自体は callable です。
これは5行目の命令によって1が出力されていることからわかります。

さて、文字列sumcallable だということは、文字列sumを関数として呼び出せるということです。

sumのような引数を必要とする関数を callable によって呼び出したいときは、call_user_func_arrayという関数をつかいます。

call_user_func_array — パラメータの配列を指定してコールバック関数をコールする

PHP: call_user_func_array - Manual

第一引数には callable を、第二引数には呼び出される関数にわたしたい式を配列にしたものを指定します。

7行目では、call_user_func_arrayの第一引数には callable である文字列sumを、第二引数には配列[2, 5]を指定しました。

これによって関数sumが呼び出され、関数sumの第一引数には2が、第二引数には5がわたされます。
このとき関数sum25の和である7を返しますので、この7echoされて7が出力されたというわけです。

余談・・

つぎのコードは今回の例の7行目をecho call_user_func('sum');にとりかえたものです。
PHP
function sum($int1, $int2) {
    return $int1 + $int2;
}

echo is_callable('sum') . PHP_EOL;

echo call_user_func('sum');

これを実行すると、もちろんエラーが出るのですが、このときのエラーメッセージはつぎのようになります。

result
PHP Fatal error:  Uncaught ArgumentCountError: Too few arguments to function sum(), 0 passed in ... and exactly 2 expected in ......

「関数sumにわたす引数が少なすぎるよ!」といわれています。
ということは、関数sumの呼び出し自体は問題なく行われたということです。

先ほどみたとおり、文字列sum自体は callable でした。
ですので、call_user_funcの引数に文字列sumを指定してあげれば、関数sumを呼び出すこと自体は問題なくできるというわけです。


例4

PHP
$hello = function () {
  echo 'こんにちは。';  
};

echo is_callable($hello) . PHP_EOL;

call_user_func($hello);
result
1
こんにちは。

1〜3行目で、変数helloに無名関数を代入しています。

無名関数は callable です。
これは5行目の命令によって1が出力されていることからわかります。

一般的なユーザー定義関数とは異なり、 無名関数 もパラメータとして渡せます。

PHP: コールバック / Callable - Manual

7行目では、call_user_funcに変数helloの値である無名関数をわたすことによって、その無名関数自身を呼び出しています。

ちなみに・・
PHP
$hello = function () {
  echo 'こんにちは。';  
};

var_dump($hello);
result
object(Closure)#1 (0) {
}

無名関数はPHPが用意しているClosureという特別なクラスのインスタンスとして実現されています。

無名関数の実装には Closure クラスを使っています。

PHP: 無名関数 - Manual


例5

PHP
class Player {
    private $name;

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

    public function getname() {
        return $this->name;
    }
}

$ichiro = new Player('イチロー');

echo is_callable([$ichiro, 'getname']) . PHP_EOL;

echo call_user_func([$ichiro, 'getname']);
result
1
イチロー

1〜10行目で、Playerクラスを定義しています。このクラスのなかでgetnameというメソッドを定義しました。

つづく12行目でPlayerクラスのインスタンスを作成し、変数ichiroに代入しています。

このとき、配列[$ichiro, 'getname']callable です。
この配列をcall_user_funcの引数に指定することで、変数ichiroに代入されたPlayerクラスのインスタンスのgetnameメソッドを呼び出すことができます。

オブジェクトのインスタンスを渡すには配列を使います。 配列の 0 番目の要素にオブジェクトを、 そして 1 番目の要素にメソッド名を指定します。

PHP: コールバック / Callable - Manual

めんどくさくなってきたので詳しく説明はしませんが、
イチローと出力されていることから、所期のメソッドが呼び出されたことがわかります。

例6

PHP
class Car {
    public static function honk() {
        echo 'ビッビー';
    }
}

echo is_callable(['Car', 'honk']) . PHP_EOL;

call_user_func(['Car', 'honk']);
result
1
ビッビー

1〜5行目で、Carクラスを定義し、そのなかでhonkという静的メソッドを定義しました。

このとき、配列['Car', 'honk']callable です。
この配列をcall_user_funcの引数に指定することで、Carクラスの静的メソッドhonkを呼び出すことができます。

静的なクラスメソッドの場合、オブジェクトのインスタンスは不要です。 0 番目の要素として、オブジェクトのかわりにクラス名を指定します。

PHP: コールバック / Callable - Manual

例7

PHP
class Car {
    public static function honk() {
        echo 'ビッビー';
    }
}

echo is_callable('Car::honk') . PHP_EOL;

call_user_func('Car::honk');
result
1
ビッビー

クラスの定義は例6とおなじです。

例6では、配列['Car', 'honk']callable であることをたしかめました。
今回の例は、文字列Car::honkもまた callable であることを表しています。

'ClassName::methodName' 形式で指定することもできます。

PHP: コールバック / Callable - Manual

クラスの静的メソッドを callable として表現する方法は二種類あるということですね。

おしまい

callable の例をたくさんみてもらいました。
これで callable とは何なのか、多少なりとも理解が深まったと思います。

また、本記事では説明が不十分な箇所も多々あるかと思います。
疑問に思うところがあったら、適宜公式マニュアル等を参照してください。

最後まで読んでいただき、ありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP/Laravelの書き方の基本ルールまとめる(PHPフレームワークLaravel入門に入る前に)part3

クラスとインスタンスについて

クラスとインスタンスとは

PHPには原本となる型を再利用して効率化を測る機能があります。それがクラスとインスタンスです。
クラスが原本となる型。
インスタンスが型を元にして作成されたものです。
型の中身には、メソッドプロパティという要素が存在しています。
メソッドが機能(関数や制御構造など)
プロバティがデータ(名前や性別といった属性)になります。
以前まとめたものがこちらになりますので参照ください。

クラス定義

覚えること

クラス定義方法
インスタンス作り方
値のアクセス方法
値の入れ方
メソッドの実行方法
コンストラクタ
クラス定義ファイルの読み込み
スタティックプロパティとスタティックメソッド

まずはこいつら
・クラス定義方法
・インスタンス作り方
・値のアクセス方法
・値の入れ方
・メソッドの実行方法
```記述例.php
<?php

class staff {
//インスタンスのプロパティ
public $name;
public $age;
//インスタンスのメソッド
public fanction hello(){
echo "こんにちは","\n";
}
}
?>

<!DOCTYPE html>



クラスを定義する


<?php
  //Staffのインスタンスを作る
  $hana = new Staff();
  $taro = new Staff();
  //プロパティの値を設定する
  $hana->name = "花";
  $hana->age = "21";
  $taro->name = "太郎";
  $taro->age = "35";
  //インスタンスを確認する
  print_r($hana);
  print_r($taro);
  //メソッドを実行する
  $hana->hello();
  $taro->hello();
?>



```
実行例.html
//print_r($hana);
//print_r($taro);
Staff Object
(
    [name] => 花
    [age]  => 21
)
Staff Object
(
    [name] => 太郎
    [age]  => 35
)
//$hana->hello();
//$taro->hello();
こんにちは!
こんにちは!
クラス定義方法.php
class クラス名{
//クラス名の文頭は基本的に大文字
      public const 定数名 = ;
      //設定した値は変更できない
      public $変数名
      //プロパティ
     
      public function メソッド名(){
      }
}
インスタンス作り方.php
$変数名 = new クラス名();
//()は省略できる
値のアクセス方法.php
$インスタンス->プロパティ名
値の入れ方.php
$インスタンス->プロパティ名 = 
メソッドの実行方法.php
$インスタンス->メソッド名(引数)

クラスのメソッドにクラス自身のプロパティを利用する時(例文にはのってない)

public function hello(){
  echo "こんにちは、"{$this->name}です!","\n";
}
//$this -> プロパティ名をつけることでアクセスが可能

つぎはこいつら
・コンストラクタ
・クラス定義ファイルの読み込み
・スタティックプロパティとスタティックメソッド

例文.php
<?php
  //Staffクラスファイルを読み込む
  require_once("Staff.php")
?>

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Staff クラスメンバーを使う</title>
</head>
<body>
<pre>
<?php
//クラスメソッドを実行
Staff::deposit(100);
Staff::deposit(150);
//クラスプロパティを確認する
echo Staff::$piggBank, "円になりました。"\n";

//インスタンスを作る
$hana = new Staff("",21);
//インスタンスメソッドを実行する
$hana->latePenalty();
//クラスプロパティを確認する
echo Staff::$piggyBank, "円になりました"\n";
?>
</pre>
</body>
</html>
出力例.html
250円になりました。
1250円になりました。

コンストラクタ.php
function__construct(引数1引数2){
  //処理
}

コンストラクタは、インスタンスを作成した時に自動で発動するメソッド。

クラス定義ファイルの読み込み.php
require_once()
//()にはひっぱり元のファイルが置いてあるパスを記入。(同じフォルダ内にある場合はファイル名でも良い)

クラス定義をする場合はクラス定義をしたファイルを作り、利用するファイル上で読み込ませるのが主流。
読み込ませるための指示がrequire_once()

スタティックプロパティとスタティックメソッド.php
class クラス名{
  //スタティックプロパティ
  public static const定数名 = ;
  public static $変数名;

  //スタティックメソッド
  public static function メソッド名(){
  }
}

クラス自身にプロパティやメソッドを付与することも可能。
生成するインスタンスが共通項として持つ物に関しては、こちらを利用する。

クラスの継承

新たにクラスを作成する際、既存のクラスを再利用して作成ができる。

覚えること

・継承の仕方
・継承したメソッド、プロパティ、コンストラクタの利用方法
・継承したクラスの情報の上書き方法(オーバーライド)

継承の仕方

継承の仕方.php
claas 子クラス extends 親クラス{
}
//新たに生成するクラス名が「子クラス」継承先のことを「親クラス」と呼ぶ

継承したメソッド、プロパティ、コンストラクタの利用方法

継承したメソッド、プロパティ、コンストラクタの利用方法.php
子クラス名 -> 継承されたメソッド名()
//継承したメソッドの利用方法

子クラス名 -> プロパティ名
//継承したプロパティの利用方法

parent::__construct(引数);
処理
}
//継承したコンストラクトの利用方法

メソッドとプロパティは通常通り記述すれば問題なし。(継承はメソッドとプロパティのコードがコピーされていると認識すれば良い)
コンストラクトの場合のみ、parent::をつける。(継承したコンストラクトを使うのか子クラスにコンストラクトを付与したのかわかるようにするため)

継承したクラスの情報の上書き方法(オーバーライド)

継承したプロパティやメソッドのデータを上書きすることができる。上書きする場合は、子クラスへ親クラスに存在するメソッドやプロパティと同じ名前でメソッドやプロパティを付与する。

トレイト

よくわかりません。
誰か教えてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【デザインパターン】PHPでTemplate Methodパターンの実装をしてみた

環境

  • PHP 7.2.18

Template Methodパターンとは

Template とと言うのは、よくいろんな人が「テンプレ」などと略すアレです。
メールなどの定型文や、作品のベースとなるひな形などの「決まった様式」のことを指すことが多いですよね。
Template Methodパターンの名前の由来もそこからきていて、決まった処理の流れなどを抽象クラスで「枠」として定めて、具体的な実装の内容は具象クラスで実装するものとなります。

スクリーンショット 2020-06-23 0.18.32.png

Template Methodパターンは何がいいか

Template Methodパターンを使うことで、似たような処理、繰り返し使われるような処理を共通化することができます。
関数による処理の共通化をすることもあるとは思いますが、クラスでそれを行うのがTemplate Methodパターンといったところです。

例題の概要

例として簡単なプログラムを作りました。
「鳥の情報を返す」テンプレートに対して、具体的な鳥のクラス(カラス,ペンギン,ダチョウ)を実装して処理を共通化させました。
最終的にそれぞれの鳥の情報を表に表示します。
イメージ図とクラス図です。

イメージ図

スクリーンショット 2020-06-23 0.20.04.png

クラス図

スクリーンショット 2020-06-23 0.19.28.png

ファイル構成

スクリーンショット 2020-06-22 0.06.30.png

ソースコード

https://github.com/nooboolean/template_method_practice

実装

まずは、テンプレートである抽象クラスの定義

今回の実装で共通となる処理は、それぞれのオブジェクト(鳥たち)の「種類」「名前」「出産方法」「移動手段」の情報をこの順番で返す処理です。
「種類」や「出産方法」などの、鳥であれば共通となる情報は、抽象クラスで実装してしまっています。
その他の鳥の種類ごとに変化する「名前」や「移動手段」に関しては、具体的な実装を具象クラスに任せています。

AbstractBird.php
<?php

abstract class AbstractBird {
    private $birdInfo;

    final public function getInfo() {
        $this->birdInfo['type'] = $this->getType();
        $this->birdInfo['name'] = $this->getName();
        $this->birdInfo['birthType'] = $this->getBirthType();
        $this->birdInfo['howToMovement'] = $this->gethowToMovement();
        return $this->birdInfo;
    }

    final private function getType() {
        return '鳥類';
    }

    protected abstract function getName();

    final private function getBirthType() {
        return '卵生';
    }

    protected abstract function gethowToMovement();
}

?>

この後は、この抽象クラスを継承した具象クラスで具体的な実装をしていきます。

次は具象クラス(カラスクラスなど)の用意

抽象クラスである「鳥」クラスができたので、後はそれらの具体的な実装を書き込む「カラスクラス」などの具象クラスを作成していきます。
「名前」や「移動手段」などの、「鳥」の種類によってそれぞれ変わる情報は、それぞれの鳥の種類のクラスに実装します。
今回は、カラスクラス/ペンギンクラス/ダチョウクラスを作成しました。

Crow.php
<?php
namespace Birds;
require_once('./AbstractBird.php');
use AbstractBird;

class Crow extends AbstractBird {

    final protected function getName() {
        return 'カラス ';
    }

    final protected function gethowToMovement() {
        return '飛ぶ';
    }
}

?>

Penguin.php
<?php
namespace Birds;
require_once('./AbstractBird.php');
use AbstractBird;

class Penguin extends AbstractBird {

    final protected function getName() {
        return 'ペンギン';
    }

    final protected function gethowToMovement() {
        return '泳ぐ';
    }
}

?>

Ostrich.php
<?php
namespace Birds;
require_once('./AbstractBird.php');
use AbstractBird;

class Ostrich extends AbstractBird {

    final protected function getName() {
        return 'ダチョウ';
    }

    final protected function gethowToMovement() {
        return '走る';
    }
}

?>

あとは、この具象クラスを実際に new してデータを取得し表示して完了です!

それぞれの具象クラスを実行して情報の表示

最後にそれぞれのクラスを new してデータを取得して表示します。
抽象クラスで処理を共通化しているため、同じ様な処理をこのようにシンプルに管理することができます。

index.php
<?php
require_once('./Birds/Ostrich.php');
require_once('./Birds/Penguin.php');
require_once('./Birds/Crow.php');
use Birds\Ostrich;
use Birds\Penguin;
use Birds\Crow;

$Ostrich = (new Ostrich)->getInfo();
$Penguin = (new Penguin)->getInfo();
$Crow    = (new Crow)->getInfo();


?>

<?php
echo "<table border = '1'>";
echo "   <tr>";
echo "        <th>種類</th>";
echo "        <th>名前</th>";
echo "        <th>出産方法</th>";
echo "        <th>移動手段</th>";
echo "    </tr>";
echo "    <tr>";
echo "        <th>$Ostrich[type]</th>";
echo "        <th>$Ostrich[name]</th>";
echo "        <th>$Ostrich[birthType]</th>";
echo "        <th>$Ostrich[howToMovement]</th>";
echo "    </tr>";
echo "</table>";
?>

<?php
echo "<table border = '1'>";
echo "   <tr>";
echo "        <th>種類</th>";
echo "        <th>名前</th>";
echo "        <th>出産方法</th>";
echo "        <th>移動手段</th>";
echo "    </tr>";
echo "    <tr>";
echo "        <th>$Penguin[type]</th>";
echo "        <th>$Penguin[name]</th>";
echo "        <th>$Penguin[birthType]</th>";
echo "        <th>$Penguin[howToMovement]</th>";
echo "    </tr>";
echo "</table>";
?>

<?php
echo "<table border = '1'>";
echo "   <tr>";
echo "        <th>種類</th>";
echo "        <th>名前</th>";
echo "        <th>出産方法</th>";
echo "        <th>移動手段</th>";
echo "    </tr>";
echo "    <tr>";
echo "        <th>$Crow[type]</th>";
echo "        <th>$Crow[name]</th>";
echo "        <th>$Crow[birthType]</th>";
echo "        <th>$Crow[howToMovement]</th>";
echo "    </tr>";
echo "</table>";
?>

ブラウザ確認

こんな感じで表示されました!完成!
スクリーンショット 2020-06-23 0.43.47.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

関数の中で関数を出力

関数の中で関数を出力

今回は勉強を進めているときに、疑問に思った
関数内での関数や変数の記述の仕方について発見があったので
書き留めておきます

まずびっくりしたのが関数内で別の関数は出力できる!ということ

<?php

$n = 2;

function test($n) {
    return $n**2;
}

function hoge($n) {
    if(test($n) < 100) { //関数外定義
        echo "100以下" . PHP_EOL;
    }
    echo "OK!!" . PHP_EOL;
}

hoge($n);

//100以下
//OK!!

過去の学習から関数内で定義した変数は関数内でしか使えない
関数外で定義した変数を使いたければ引数で渡せ

これを学んだばかりの私は先入観から

「関数においても同じだろう」

このような安易な考えから

<?php

$n = 2;

function test($n) {
    return $n**2;
}

$fuga = test($n);//わざわざ変数に直す

function hoge($fuga) {
    if(test($fuga) < 100) {
        echo "100以下" . PHP_EOL;
    }
    echo "OK!!" . PHP_EOL;
}

hoge($n);

//100以下
//OK!!

という風にかなり遠回りな記述をしていました。

そしてさらに驚いたのは、

<?php

$n = 2;

function hoge($n) {
    function test($n) {//関数内で関数定義
        echo "2乗します" . PHP_EOL;
        return $n**2;
    }
    if(test($n) < 100) {
        echo "100以下" . PHP_EOL;
    }
    echo "OK!!" . PHP_EOL;
}

hoge($n);
test($n);//関数外で出力

// 2乗します
// 100以下
// OK!!
// 2乗します

関数の中で定義した別の関数が、関数の外で出力できることです。

もはや{}の囲いから外へ脱走しまくっていますw

用途は少なそうだが頭に入れておいて損はなさそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む