20201113のPHPに関する記事は16件です。

vimで.phpファイルに書いたhtmlを自動でインデントする方法

" Better indent support for PHP by making it possible to indent HTML sections
" as well.
if exists("b:did_indent")
  finish
endif
" This script pulls in the default indent/php.vim with the :runtime command
" which could re-run this script recursively unless we catch that:
if exists('s:doing_indent_inits')
  finish
endif
let s:doing_indent_inits = 1
runtime! indent/html.vim
unlet b:did_indent
runtime! indent/php.vim
unlet s:doing_indent_inits
function! GetPhpHtmlIndent(lnum)
  if exists('*HtmlIndent')
    let html_ind = HtmlIndent()
  else
    let html_ind = HtmlIndentGet(a:lnum)
  endif
  let php_ind = GetPhpIndent()
  " priority one for php indent script
  if php_ind > -1
    return php_ind
  endif
  if html_ind > -1
    if getline(a:lnum) =~ "^<?" && (0< searchpair('<?', '', '?>', 'nWb')
          \ || 0 < searchpair('<?', '', '?>', 'nW'))
      return -1
    endif
    return html_ind
  endif
  return -1
endfunction
setlocal indentexpr=GetPhpHtmlIndent(v:lnum)
setlocal indentkeys+=<>>

これを~/.vim/indent/php.vimの中に書けばオッケー!

参考:
https://vim.fandom.com/wiki/Better_indent_support_for_php_with_html

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

PHP 復習2

PHP復習の続き
ちょっとだけ

関数

自分で作るやつと組み込み関数がある
組み込み関数は調べたら色々出てくるので割愛。(組み込み関数忘れてた:sweat_smile:
rand(a,b)とかあったよ!これは数字a〜bの間の整数をランダムにかえしてくれるよ!

関数の作り方

function 関数名(){処理}

関数の呼び出し

関数名();

formの受け取り

 <form method="post" action="送信先">
        <input type="text" name="キー名">
</form>
受け取るphp側
echo $_POST[キー名];

$_POSTの中身は連想配列になっている。
キー名:name、値:実際にフォームに入力した値(value)
となるようになっている。
なので、nameの中身は受け取るときにわかりやすいものにしとくとよい。
キー名は''で囲むのを忘れない

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

[PHP] Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? という警告

どんな警告か?

この警告は、forループ内のswitch文で「continue」を記述した場合に表示されます。
switch文内部では「continue」が「break」と同じ動作となるそう。
以下、公式リファレンスを引用

注意: PHP では、continue の動作に関しては switch 文がループ構造とみなされます。
continue に引数を渡さなかった場合の動きは break と同じですが、間違いの元なので警告が生成されます。
switch がループ内にある場合、 continue 2 とすると、外側のループの次回の処理から続行します。

引用元:PHP公式リファレンス

じゃあどうすればいいの?

forループ内のswitch文で「continue」を使用したい場合、
continue 2」と指定します。
これで、「continue 2」は、switch文の外にあるforループを対象とします。
以下、参考コード

example.php
for ($i = 0; $i < 10; $i++) {
    switch (true) {
        case $i % 2 == 0 :
            // 偶数のときだけ実行する処理
            break;
        default:
            // 奇数のときはスキップされる
            continue 2;
    }
}

以上です。

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

PHP復習

最近、あまりPHP書いてないので、なまらないように見直す。
ついでに後で見返すようにまとめ!:dancer_tone3::dancer_tone3::dancer_tone3:

文字列結合

.

$fruits = 'orange';
echo $fruits.'ジュース'

変数展開

"{$変数}"
:warning:出力するときはダブルクオーテーションで囲む。
シングルクオーテーションだと{$変数}がそのまま文字列として出力される

$food = burger;
echo "{$food}ください";

かつ、または

かつ&&
または||

switch文

あんまり使わない?らしい

    switch (条件式){
      case 0:
        echo '大吉です。';
        break;
      case 1:
        echo '中吉です。';
        break;
      default:
        echo '凶です。';
        break;
    }

breakがないと次のbreakが現れるまで、後のcaseも処理されてしまうので、忘れないように
defaultは当てはまるcaseがないときに処理される。
caseの部分にbreakを一つも設定していないと、下のcaseまで処理される。breakを忘れてはいけない。

よくわからないところ

defaultは該当するcaseがない場合に処理されるもの。と書いてあったけど・・・?

下のコードはあえてbreakを書き忘れたもの。

$num = 0
    switch ($num){
      case 0:
        echo '大吉';
      case 1:
        echo '中吉';
      default:
        echo '凶';
        break;
    }
//実行結果:大吉中吉凶

本来なら、case0で大吉が出力される。けど、breakがないので次のcaseも処理される。

  • 大吉中吉 と出力されてしまう ←わかる
  • 大吉中吉凶 と出力されてしまう ←わからない

defaultは該当するcaseがない場合に処理される。(しつこい)
ので、今回case0で該当したから、defaultは処理されない!と思っていた。switch文わからない:joy:
そもそも条件式のところにいきなり数字を入れても、急に変数を定義してもどうにかなってしまうのよくわからない。。。

配列・foreach文

$変数(配列)名 = array(配列中身1,配列中身2)
foreach(連想配列 as 配列を一つずつ入れる用変数){処理}

$names = array('やまだ','たなか','さとう');
echo '僕は'.$names[2];
$names[] = 'きむら';      // 配列の末尾に追加

foreach ($names as $name){
echo $name;
}

連想配列・foreach文

$配列名 = array('キー名' => '値1,・・・)
foreach(連想配列 as キー名が入る変数 => 値が入る変数){処理}

    $student1 = array(
      'num'=> 1,
      'name'=> 'Ann',
      'age'=> 14);

      $student1['club'] ='tennis';       //追加

      echo '名前:'.$student1['name'];
      echo "{$student1['age']}歳";
    foreach($student1 as $key => $value){
      echo $key.':'.$value.'<br>';
    }
//1周目 num:1 2周目 name:Ann 3周目 age:14 club:tennis

fot文

for($i=初期値;ループ条件;$iの更新){繰り返す処理}

while文

$i=初期値;while($iループ条件){繰り返す処理;$iの更新}
ループ条件はいつかfalseになるようにしないと、無限ループになってしまうので注意。

continue

breakでは完全にループを抜けてしまう。
一定以上では処理を止めたいときはbreak、
一定の条件だけ処理をしたくないとかってときはcontinueを使う。

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

項目をランダム選択しその結果(good/bad)もランダムにする。ただしbadの上限あり

こんにちは。@mashiです。

この記事は一応この記事( https://qiita.com/mashi/items/93a088c90839251ef820 )の続きです。

【大項目/小項目/結果(good/bad)という表があり、各大項目にて1つの小項目を選択し、good/badもランダムにする】というものです。

文章だけではよく分からないため、下記の出力イメージです。
技術・勤怠・コミュニケーションにてそれぞれ小項目1つをランダムで選び、goodかbadもランダムにするというものです。
badの個数も0~1の間でランダムです。

大項目 小項目 good bad
技術 速度
技術 品質
技術 納期
技術 ドキュメント
勤怠 遅刻
勤怠 勤怠忘れ
コミュニケーション 挨拶
コミュニケーション タスク共有
コミュニケーション 会議内容

前回のコードを用いて実装すると下記のような感じになりました。(実際に動作しているコードとは異なるためちょこちょこ端折ってます)

// ランダム出力する大項目の個数
$major_items_num = 3;
// badの数は0~1個
$bad_num = rand(0, 1);
// 大項目の配列
$major_items_array = array('skill', 'attendance', 'communication');
$bad_major_items_array = array();

if ($bad_num > 0) {
    $random_array = array();
    shuffle($major_items_array);

    // badの大項目
    $bad_major_items_array[] = array_slice($major_items_array, 0, $bad_num);
}

for ($i = 0; $i < count($major_items_array); $i++) {
    // 各大項目にて小項目の選択とgood/badの決定
    if (in_array($major_items_array[$i], $bad_major_items_array, true)) {
        $evalution = 'bad';
    } else {
        $evalution = 'good';
    }
    // 〇を付けるセルの位置(選択された小項目かつgood/bad)
    $cell_coordinate = getMajorItemCell($major_items_array[$i], $evalution);
}

function getMajorItemCell ($item_name, $evalution) {
    $col_num = '';
    $row_num = '';
    $skill_base_row = [技術の開始行];
    $attendance_base_row = [勤怠の開始行];
    $communication_base_row = [コミュニケーションの開始行];

    if ($evalution == 'bad') {
        $col_num = [badの列番号];
    } else {
        $col_num = [goodの列番号];
    }

    // 選択された小項目の行番号
    switch ($item_name) {
        case 'skill': // 技術
            $row_num = rand(0, 1) + $skill_base_row;
            break;
        case 'attendance': // 勤怠
            $row_num = rand(0, 4) + $attendance_base_row;
            break;
        case 'communication': // コミュニケーション
            $row_num = rand(0, 1) + $communication_base_row;
            break;
        default:
            break;
    }

    $cell_coordinate = $col_num . $row_num;

    return $cell_coordinate;
}

なんだかんだ長いコードになってしまったので、もっとスッキリできそうな予感がします。
時間がある時に見直して修正します。

コメントがあればいただければ幸いです。

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

PHPのインクルード4つを解説

まえがき、インクルードとは?

PHPにはインクルードという便利な処理があります。

各htmlページに同じ処理を何度も書く手間を省いて、共通事項になっている処理を別所から参照できる機能でもあるし1つのページの複雑化/長文化を避ける為に別所にソースコードを仕分ける機能とも言えます。
特に大きくなってしまったウェブページ/サイトを修正する手間を効率化してくれるものと言えるでしょう。

しかし、このPHPのインクルード処理は4種類もの処理があります。そしてそれらは微妙に使い方が違ってきますのでそれを解説したいと思います。

読み込みエラーがある場合で、その後のデータを処理する/しない。
そして、1度だけ読み込む/何度でも読み込む
の、違いで4種類に分かれています。

「include」…読み込みに失敗しても処理継続するインクルード

例えば、includeを使って、「text.php」を開こうとした際に、「text.php」が無いと言う時、そのIncludeはエラーと処理して、その後の処理を読み込んでいきます。
下記の例だと、

test.php
<? include('./text.php'); ?>
<p>エラー後読み込みテスト</p>

という処理で、

test.php
Warning: include(test.php): failed to open stream: No such file or directory in C:\xampp\htdocs\index.php on line 11

Warning: include(): Failed opening 'test.php' for inclusion (include_path='C:\xampp\php\PEAR') in C:\xampp\htdocs\index.php on line 11

エラー後読み込みテスト

と出ます。最後の「

エラー後読み込みテスト

」がちゃんと読み込まれている所がミソです。

エラーがあってもとりあえず処理を継続させたい時に使います。

「require」…読み込みに失敗したらそれ以上の処理をしないインクルード

requireを使って、「text.php」を開こうとした際に、「text.php」が無いと言う時、エラーと処理してしまいます。
下記の例だと、

test.php
<? require('./text.php'); ?>
<p>エラー後読み込みテスト</p>

という処理で、

test.php
Warning: require(test.php): failed to open stream: No such file or directory in C:\xampp\htdocs\index.php on line 11

Fatal error: require(): Failed opening required 'test.php' (include_path='C:\xampp\php\PEAR') in C:\xampp\htdocs\index.php on line 11

と出ます。

エラー後読み込みテスト

」読み込まれていませんね。

確実にエラーに気づきたい、もしくは予期せぬ動きが出たときに容赦なくエラー処理にしたいならこちらを使います。

1度だけ処理する「include_once()」「require_once()」

最後に紹介するのは、同じスクリプトの中で、1度限り処理するinclude/requireの、「include_once()」「require_once()」です。

実は、includeもrequireも、2回記述がある場合、2回読み込んでくれます。何度でも読み込んでくれるのです。

しかし、そういう処理をさせたくはないという時は、この「include_once()」「require_once()」を使うと、1回限りの利用に抑えてくれます。

関数の定義などを行う場合、この「require_once()」が便利です。関数定義は1度しか読み込まない前提ですから、万が一の定義上書きを避ける事ができます。

まとめ

「include()」…読み込みに失敗してもとりあえず処理継続。
「include_once()」…読み込みに失敗してもとりあえず処理継続。1度しか読み込まない。
「require()」…読み込みに失敗したらエラー扱い。
「require_once()」…読み込みに失敗したらエラー扱い。1度しか読み込まない。

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

PHP入門する①

少しPHPに関して勉強しようと思います。
というのも、今までRubyonRailsで個人開発していたのですが、
ほかの言語の特性も把握しておこうかな、ということで公式リファレンスを読みながらメモ書きしていく事になった次第です。

PHPタグ

<?php  ?>

このPHPタグで囲んだ範囲がPHPコードということになります。
ファイル内のどこに書かれていてもPHPがこのタグを探してくれるので、どんな形式のドキュメントにも埋め込むことができます。

またドキュメントの最後の行が終了タグ

?>

この場合は省略することが望ましいです。
この終了タグの後に空白や文字列が入るとPHPが予期せぬ動作をする可能性がある為です。

条件式
PHPにももちろん条件式はあります。
if文を見てみます。

<?php  if($foo == 100){
  echo "fooは100です";
  }else{
  echo "fooは100じゃない";
  }
?>

一般的なif文だと思います。
$foo == 100が真なら、echo "fooは100です";
を返し、それ以外なら"fooは100じゃない";
を返す式ですね。

また、このようにも書けます

<?php if ($foo == 100): ?>
  fooは100です。
<?php else: ?>
  fooは100じゃない
<?php endif; ?>

PHPは式を論理値で評価します。
そして次の式までの間をブロックとし、ブロック毎に式を評価します。
{}この記号は:で省略されています。

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

重複しないランダムな数値を取得する

こんにちは。@mashiです。

重複しないランダムな数値が欲しいなーと思いましたので作りました。

ちなみに、重複してよいのであればこれですよね。

// 連続している数値候補の中から重複する可能性がある値を取得する
for ($i = 0; $i < 3; $i++) {
  $num = random(0, 1);
}

重複しない数値が欲しい際というとif文かなと最初は思ったのですが、改修の際にあちこち触ることになりそうAnd見づらそうと思ってしまいモヤっとしたので、違う観点で作りました。というか、そもそもこういう関数って存在しないのかな。

// 連続している数値候補の中から重複しない値を取得する
function randomNotDuplicate ($from_num, $to_num, $count) {
  $number_array = range($from_num, $to_num);
  $random_array = array();
  shuffle($number_array);
  $random_array = array_slice($number_array, 0, $count);

  return $random_array;
}

念のため簡単に解説です。

1.from_numからto_numまでの連続する数値を最初に配列に入れます
2.上記配列の中身の順番をシャッフルします
3.for文にてcountの個数だけシャッフル後の配列番号0から取得しrandom_arrayに格納します

条件分岐を使わないため後から見た際に分かりやすいし、個数や上限下限の変更も効くので問題なさそうかなと思っています。

このコードを利用・拡張することで、なんかできそうだなーと考えています。
というより、実は今回この実装を行った理由は、【4つの大項目それぞれについて、各大項目内で1つだけランダム小項目を選択しgood/badをランダムに選択しエクセルに出力する。なお、badの個数は0~1にする】という機能が必要だったからです。

予想以上に長くなり、本来のタイトルから若干それた気がするので別の記事( https://qiita.com/mashi/items/6f655d8202600966e85e )として投稿させていただきます。
ご興味があればぜひご覧ください。

なにかあればコメントをいただければ幸いです。

2020/11/13
@tadsan 様のご指摘でarray_slice()を利用するよう修正

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

PHPでSingly linked list

まじめにデータ構造などの学習をしてなかったんですが、最近ちょっとずつやり始めたので、業務で使用しているPHPでアウトプットしてみます。

Singly Linked list

データを持つノードが連なったデータ構造で、各ノードは次or前のノードへのリンクを持っています。
いくつか種類がありますが、今回扱う Singly linked listは、データと次のノードへのリンクのみを持つノードが連なったものです。

Singly-linked-list.png

PHPで実装してみる

クラス定義

まずノードのクラスを実装。
データ用フィールドと次のノードへのリンク用のフィールドを持っています。

<?php
class NodeSingly
{
    public $data;
    public $next;

    public function __construct($data, NodeSingly $nextNode = null)
    {
        #データ
        $this->data = $data;
        #次のノード
        $this->next = $nextNode;
    }
}

次にlinked listのクラスを実装。
先頭ノード用のフィールドを持っています。

class SinglyLinkedList
{
    public $head;

    public function __construct(NodeSingly $head = null)
    {
        $this->head = $head;
    }

}

メソッドの実装

linked listをいろいろ操作するためのメソッドを、SinglyLinkedListクラスにいくつか実装してみます。

内容は以下の通りです。

  • 新しいノードをリストの最後に追加
  • 新しいノードをリストの先頭に追加
  • 新しいノードを任意のデータを持つノードの後に追加
  • 任意のデータを持つノードを削除
  • リストを逆順に並び替え

なお、コーナーケース的なものは今回考慮してないです

新しいノードをリストの最後に追加

リストにノードがない場合は先頭に追加。それ以外の場合はループ処理で終端ノードを見つけ、終端ノードのnextを新しいノードに設定。

    public function insertAtEnd($data)
    {
        $newNode = new NodeSingly($data);
        #リストが空の場合は先頭に追加
        if (is_null($this->head)) {
            $this->head = $newNode;
            return;
        }

        $lastNode = $this->head;
        while ($lastNode->next) {
            $lastNode = $lastNode->next;
        }
        $lastNode->next = $newNode;
    }

新しいノードをリストの先頭に追加

既存の先頭ノードを新しいノードのnextに設定し、新しいノードをheadに設定。

    public function insertAtStart($data)
    {
        $newNode = new NodeSingly($data);
        $newNode->next = $this->head;
        $this->head = $newNode;
    }

新しいノードを任意のデータを持つノードの後に追加

ループさせて対象のデータを持つノードを探して、そのノードのnextに新しいノードを設定。
対象のデータを持つノードがなければなにもしない。

    public function insertAfterNode($targetData, $data)
    {
        $currentNode = $this->head;

        while ($currentNode->next) {
            if ($currentNode->data === $targetData) {
                break;
            }
            $currentNode = $currentNode->next;
        }

        if (is_null($currentNode)) {
            return;
        }

        $newNode = new NodeSingly($data);
        $newNode->next = $currentNode->next;
        $currentNode->next = $newNode;
    }

任意のデータを持つノードを削除

先頭ノードのデータが対象のデータだった場合、先頭ノードのnextを先頭ノードに設定。
それ以外の場合はループさせて対象のノードを見つける。見つけたらそのノードを飛ばすようにnextを設定。

    public function remove($data)
    {
        #先頭ノードの場合
        $currentNode = $this->head;

        if ($currentNode && $currentNode->data === $data) {
            $this->head = $currentNode->next;
            $currentNode = null;
            return;
        }

        $prevNode = null;
        while ($currentNode && $currentNode->data !== $data) {
            $prevNode = $currentNode;
            $currentNode = $currentNode->next;
        }

        if (is_null($currentNode)) {
            return;
        }
        #対象ノードを飛ばしてリンクを設定
        $prevNode->next = $currentNode->next;
        $currentNode = null;
    }

リストを逆順に並び替え

先頭ノードから順番に、リンクを逆方向に設定してゆきます。
最終的に終端ノードが返ってきたら、それを先頭に設定します。

    public function reverse()
    {
        $sort = function (NodeSingly $targetNode = null, NodeSingly $prevNode = null) use(&$sort) {
            if (is_null($targetNode)) {
                #nextがnullのノード(終端)を返す
                return $prevNode;
            }
            #nextの値が変わるので一旦変数に格納
            $nextNode = $targetNode->next;
            #次のノードへのリンクを逆方向に設定
            $targetNode->next = $prevNode;
            #操作が終わったノードは '前のノード' とする
            $prevNode = $targetNode;
            #次に見るノード
            $targetNode = $nextNode;
            return $sort($targetNode, $prevNode);
        };

        #終端が返ってくるのでそれを先頭に設定する
        $this->head = $sort($this->head, null);
    }

動かしてみる

メソッドを実装したので動作させてみます。
その前に出力用に整形するメソッドを実装しておきます。

    public function output()
    {
        $currentNode = $this->head;
        while ($currentNode) {
            echo $currentNode->data."\n";
            $currentNode = $currentNode->next;
        }
    }

それではリストを作成して出力してみます。

最後にノード追加

$list = new SinglyLinkedList();
$list->insertAtEnd(1);
$list->insertAtEnd(2);
$list->insertAtEnd(3);
$list->insertAtEnd(4);
$list->output();

1
2
3
4

先頭にノード追加

$list = new SinglyLinkedList();
$list->insertAtEnd(1);
$list->insertAtEnd(2);
$list->insertAtEnd(3);
$list->insertAtEnd(4);
$list->insertAtStart(420);
$list->output();
420
1
2
3
4

任意のノードの後ろに追加

3というデータを持つノードの後に追加してみます。

$list = new SinglyLinkedList();
$list->insertAtEnd(1);
$list->insertAtEnd(2);
$list->insertAtEnd(3);
$list->insertAtEnd(4);
$list->insertAfterNode(3, 420);
$list->output();
1
2
3
420
4

逆順に並び替え

さきほどのリストを逆順に並び替えます。

$list = new SinglyLinkedList();
$list->insertAtEnd(1);
$list->insertAtEnd(2);
$list->insertAtEnd(3);
$list->insertAtEnd(4);
$list->insertAfterNode(3, 420);
$list->reverse();
$list->output();
4
420
3
2
1

ノードの削除

さきほどのリストから3というデータを持つノードを削除します。

$list = new SinglyLinkedList();
$list->insertAtEnd(1);
$list->insertAtEnd(2);
$list->insertAtEnd(3);
$list->insertAtEnd(4);
$list->insertAfterNode(3, 420);
$list->reverse();
$list->remove(3);
$list->output();
4
420
2
1

ちゃんと動いてますね

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

【Vagrant】VagrantでLAMP開発環境を整える(centos+apache+MySQL+PHP)

自分用のメモとして残します。

やり方

1.VagrantのBoxダウンロード~mysql、apache、phpインストール

いろいろ探しましたが、Masaki Yamadaさんのスタッフブログに投稿されたものが一番わかりやすく且つ丁寧で、初心者でも構築しやすいと思います。

(外部サイト)VirtualBox + Vagrantで「CentOS7 + LAMP環境」を構築する

手順通りであれば http://192.168.33.10/phpmyadmin にアクセスしてPHPMyAdminが表示されれば、ひとまずLAMP環境がきちんと構築できています。
尚デフォルトドキュメントルートは/var/www/htmlになっています。

尚、CentOSのタイムゾーン、mysqlのmy.cnf調整等は必要なので、後述で調整の仕方を説明します。

2.調整等

ホストOS側調整

ゲストOSマシンのスペックを指定

お好みではありますが、Vagrantファイルに下記を追記してゲストOSのスペックを調整しましょう。

Vagrantファイル
#※追記するのは`Vagrant.configure("2") do |config|`の内側です。
  config.vm.provider "virtualbox" do |vb|
    vb.cpus = 2
    vb.memory = 2048
    vb.gui = true
  end

vb.gui = trueはゲストOSの画面を表示するオプションです。
私だけかもしれませんが、たまにvagrant upに失敗するため、GUIを表示させないと問題の切り分けや、ゲストOS側での調査もできないので、個人的には設定するのをおすすめします!

ゲストOS側(CentOS側)調整

以降の作業をする前にとりあえず、rootに切り替える。

sudo su - 
#rootに切り替わり、カレントディレクトりが/rootになる

MySQLのMy.cnfを調整してマルチバイト対応

下記の記事を参考に調整。
(参考記事)mysqlで日本語を扱えるようにする

CentOSのタイムゾーンを日本に設定

timedatectl set-timezone Asia/Tokyo

CentOSにインストールされているパッケージのアップデート

カーネル等の更新も、もしかしたらあるため、めちゃくちゃ時間かかると思います。

yum update
# -yオプション付けると確認をスキップ

※セキュリティアップデートだけでよい人は以下を実行

yum --security update

最後に

ここまで構築しておけば、調子がよくなければ、LAMP構築の状態のboxから開始できるようになるため、boxファイルを作成することをお勧めします。
(参考)【Vagrant】現在のOSイメージをvagrantのboxとして保存して他のエンジニアに共有する。

以上。

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

PHP超初心者が書くPHP超初心者向け文法まとめ

はじめに-この記事の投稿理由-

ProgateでPHPを学び始めて、いざアプリ開発!!!と意気込んだわ良いものの「あれ、このやり方どうやるんだっけ?」と毎回Progateを開いて確認・ネットで調べる日々。最低限の基礎だけでもサラッと見直せる一覧があったら楽だと思いこの記事を書きました。同じような思いの方の少しでも役に立てれば幸いです。また、私自身はプログラミング初心者です。もし誤った情報があればご指摘していただけるととてもありがたいです。

○この記事の想定対象読者
・過去の自分
・PHP 超初心者:

では、本題へ入ります↓↓↓

PHPの書き方・出力方法

qiita.php
//書き方
<?php ~ ?>  //phpの命令は~の部分に記述します

//出力方法
<?php
 echo 'hello'; //echo:PHPへの命令をブラウザに出力する場合に使用します
//出力結果:hello

echoの使い方

echo (半角スペース) (出力したいもの) ; (セミコロン←行の終わりを示すためのもの)
・出力したいものには*1 文字列/数値/*2 変数を入れることができます。
*1 文字列/数値/
・・・プログラミングにはデータの種類(データ型)というものがあり表記の仕方が異なります。

qiita.php
//文字列
echo 'hello'; 
echo "hello" //文字列は(':シングルクォーテーション)もしくは(":ダブルクォテーション)で囲みます

//数値
echo 5 //出力結果:5

//文字列と数値の違い
echo "5 + 5"; //結果:5+5 (クォテーションで囲っているため全て文字列と判断されそのまま出力される)
echo 5 + 5;   //結果: 10 (クォテーションがないため、数値として扱われ計算結果が出力される)

補足:なぜこのような文字と数値で表記の違いがあるのか???
PHPに限らずプログラミング言語はパソコンに「〜してください」と指示するためのもので、いわゆる「パソコン語・機械語」のようなものです。つまり私たち人間の言葉では理解できないので、このような違いがあります。

*2 変数(私がプログラミングを始めて最初に???となった所なので私の心情多めです)
・・・「様々な文字列や数値を入れておく箱」という説明をよく見ます。また、この箱を使い回すことで同様の処理が簡単におこなえるようになるそうです。私はこれがピンときませんでした。百聞は一見にしかずということで↓↓↓

qiita.php
//変数の定義(詳細は後ほど記します)
$name = 'Ken'; //$変数名 = 値; 
echo $name; //結果:Ken

ふむふむ、、定義の仕方は分かった。。。。で、これをどう使うの?となったので↓↓↓に例を上げておきます。
(私が変数って便利だな!!と思えた例えなので、ものすごく極端な例となっています)

qiita.php
//3人での会話
echo 'こんにちは、Aです'
echo 'こんにちは、Bです'
echo 'こんにちは、Cです'

この挨拶を全て「おはようございます」に変更する場合全て、入力し直す必要があり手間がかかります。
この時に変数を利用すると、とても楽になります。

qiita.php
$greet = 'こんにちは';
//3人での会話
echo '{$greet}、Aです' //結果:こんにちは、Aです
echo '{$greet}、Bです' //結果:こんにちは、Bです
echo '{$greet}、Cです' //結果:こんにちは、Cです

//挨拶を「おはようございます」に変えたい
$greet = 'おはようございます';
echo '{$greet}、Aです' //結果:おはようございます、Aです
echo '{$greet}、Bです' //結果:おはようございます、Bです
echo '{$greet}、Cです' //結果:おはようございます、Cです
//文字列の中に変数を入れる場合は、{}で囲みます

上のように変数を利用すると変更箇所が1つで済むので非常に便利です。
(実際はこのような単純なものに使われるのではなく、クラス、プロパティ、インスタンスなどと絡めて使われます。あくまでも変数の「箱の中にデータを保存して使いまわせる」をシンプルに示した例です。)

また、変数名は何でも良いというわけではなく以下のようなルールがあります。

・必ず$からはじまる

・使えるのは半角英数字、_(アンダースコア)

・大文字小文字は区別される

・各単語の先頭は大文字(例:$LastName)

・$のあとに数字は使えない(例:$name123 ○、$123name ×)

変数の様々な使い方

1.変数の値の更新

変数とは読んで字の如く「変わる数」です。つまり、一度定義した変数を後から変更することができます。

qiita.php
$name = "Ken"; 
echo $name; //結果:Ken
//変数の値を上書き
$name = "Tom"; 
echo $name //結果:Tom

2.算術演算子

qiita.php
$x = 6 + 2 //結果:8   加算(足し算)                  
$x = 6 - 2 //結果:6   減算(引き算)
$x = 6 * 2 //結果:12  乗算(掛け算) 「×」ではなく、「*」を使う
$x = 6 / 2 //結果:3   除算(割り算)  「÷」ではなく、「/」を使う
$x = 6 % 5 //結果:1   剰余(あまり)  「%」はあまりを表すので1となる

3.変数に数字を足す

変数に文字を足す場合は、省略した書き方が存在します。また、足し算以外の全ての計算に置いて省略形が存在します。

qiita.php
    //基本形  →  省略形
$x = $x + 5;  $x += 5;
$x = $x - 5;  $x -= 5;
$x = $x * 5;  $x *= 5;
$x = $x / 5;  $x /= 5;
$x = $x % 5;  $x %= 5;

4.変数に数字を足す(特別な省略形)

変数に足す数が「1」の場合だけ、上記の省略形からさらに省略することができます。(引き算も同様に省略できます。)

qiita.php
    //基本形  →  省略形  →  省略形
$x = $x + 1;  $x += 1;   $x++; //xに1を足す
$x = $x - 1;  $x -= 1;   $x--; //xから1引く
//値が1かつ足し算・引き算の時だけこの省略形は使用できます

//また、「+」「-」を変数の前に記述するか後に記述するかで実行結果が変わってきます
$x = 6;
echo $x++; //結果:6
//変数の後ろに「++」を記述した場合、echo実行後に「++」が処理される(1足される)ので、結果は6となります。

echo ++$x; //結果:7
//変数の前に「++」を記述した場合、echo実行前に「++」が処理される(1足される)ので、結果は7となります。

さいごに

今回はここまでとなります。echoでの出力・算術演算子・変数など基礎の基礎を記述したものなので、冒頭でも述べましたが私と同じような超初心者の方の助けになれれば幸いです。次回の記事では条件分岐・配列などもう少し進んだ内容を投稿します。ご覧いただきありがとうございました。

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

PHPのerror_log関数を使用しての仮想環境vagrantへのpath

自分用忘備録
var_dump等で値を確認できない時。
仮想環境vagrant上で開発時にデスクトップ上にerror_logファイルを作成しようとしたが、仮想環境のpathが違い少しハマった。

経緯

画面がエラーで表示されず、値を返さない裏側の処理があり、
デバッグで変数情報をファイル出力するerror_log関数で追っていくことにした。

開いているディレクトリは権限があり、
error_log(print_r($Data,true),"3","/vagrant/system/debug.log");

$Data = 値を確認したい変数をセット
/vagrant/system/ = vagrant上のpath(ディレクトリsystem以下にファイルが作成される)
debug.log = 新規ファイル名(なんでも構わない)

ファイルが作成された後は同じファイル名で再度叩くと同ファイルに値の内容が上書きされる。

vagranのpath確認コマンド

$vagrant up
↓
$vagrant ssh(vagrantへログイン)
↓
[vagrant@localhost ~] $cd /vagrant/
 複数のファイルorディレクトリ名    system/
↓
[vagrant@localhost ~]$cd /vagrant/system/
↓
[vagrant@localhost system]$pwd
/vagrant/system
↓
[vagrant@localhost system]$ls (念の為systemディレクトリ内ファイル確認)

問題なさそうなら、値を調べたい箇所に以下error_log関数を記述。
error_log(print_r($Data,true),"3","/vagrant/system/新規ファイル名");

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

WordPressのREST APIにアイキャッチ画像のURLを追加する

WordPressのREST APIでアイキャッチ画像のURLを取得して表示しようとしたら画像のIDしか返ってこなくて微妙だったのでURLが返ってくるようにカスタマイズしたメモ。

環境

  • WordPress 5.5.1
  • PHP7.4.0

コード

functons.php
add_action('rest_api_init', 'customize_api_response');
function customize_api_response() {
  // アイキャッチ画像のレスポンスを追加する投稿タイプ
  $post_types = ['hoge', 'fuga'];

  foreach ($post_types as $post_type) {
    register_rest_field(
      $post_type,
      'thumbnail',
      array(
        'get_callback'  => function ($post) {
          $thumbnail_id = get_post_thumbnail_id($post['id']);

          if ($thumbnail_id) {
            // アイキャッチが設定されていたらurl・width・heightを配列で返す
            $img = wp_get_attachment_image_src($thumbnail_id, 'large');

            return [
              'url' => $img[0],
              'width' => $img[1],
              'height' => $img[2]
            ];
          } else {
            // アイキャッチが設定されていなかったら空の配列を返す
            return [];
          }
        },
        'update_callback' => null,
        'schema'          => null,
      )
    );
  }
}

これでAPIのレスポンスに下記のように thumbnail という項目が含まれるようになりました。

thumbnail: {
  url: "https://xxxxxxxxxx.jpg",
  width: 900,
  height: 600
}

追記

https://xxxxx/wp-json/wp/v2/posts?_embed のようにパラメータに _embed をつけたら取得できるようになると教えてもらいました。
が、かなり階層の深いところに取りにいかないといけないようです。

https://webtatan.com/blog/wordpress/wp-rest-api-v2-json

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

PHP で湯婆婆を実装してみる (OOP)

はじめに

様々な言語で湯婆婆を実装するのが流行っているようなので PHP で実装しました。

作った後で既に PHP で実装している人がいることに気が付きましたが、
なるべくオブジェクト指向っぽく表現した版という名目でここに供養します。

実行環境

  • PHP 7.4

登場するクラス

  • メインクラス: Main (プログラムの入り口)
  • 契約書クラス: Contract
  • 湯婆婆クラス: Yubaba
  • あなたクラス: You (作中で言うところの千尋のこと)

実装 (一部抜粋)

メインクラス

プログラムの入り口です。

class Main
{
    public static function main(): void
    {
        // 白紙の契約書を持たせた状態で「湯婆婆」のインスタンスを生成する
        $yubaba = new Yubaba(Contract::createBlankContract());

        // 契約を開始する (戻り値は湯婆婆の持つ白紙の契約書)
        $contract = $yubaba->startNewContract();

        // 「あなた」のインスタンスを生成する
        $inputName = static::_getStdinInteractively();
        $you = new You($inputName);

        // 「湯婆婆」から渡された契約書に「あなた」が署名する
        $you->signContract($contract);

        // 強制的に名前を奪う
        $yubaba->forciblyRename($you);
    }

    // 対話型シェルで標準入力から何らかの文字列を得る
    // 元ネタを踏襲し入力値のバリデーションは行わない
    private static function _getStdinInteractively(): string
    {
        $fp = fopen('php://stdin', 'rb');
        return trim(fgets($fp));
    }

契約書クラス

データクラスです。署名を行うことができます。

class Contract
{
    private string $_signatureName;

    // 白紙の契約書を作成する
    public static function createBlankContract(): self
    {
        return new self('');
    }

    // インスタンスは非公開 (同クラスの静的メソッドを介した生成のみを許可する)
    private function __construct(string $_signatureName)
    {
        $this->_signatureName = $_signatureName;
    }

    // 契約書に署名する
    public function sign(string $name): void
    {
        $this->_signatureName = $name;
    }
}

湯婆婆クラス

喋ります。

class Yubaba
{
    // 湯婆婆の持つ契約書
    private Contract $_contract;

    public function __construct(Contract $contract)
    {
        $this->_contract = $contract;
    }

    // 契約を開始する (記入のため契約書を返す)
    public function startNewContract(): Contract
    {
        echo '契約書だよ。そこに名前を書きな。' . PHP_EOL;
        return $this->_contract;
    }

    // 強制的に改名させる
    public function forciblyRename(You $you): void
    {
        $name = $you->getName();
        echo sprintf('フン。%sというのかい。贅沢な名だねぇ。', $name);

        $newName = static::_pickOneCharacter($name);
        echo sprintf('今からお前の名前は%1$sだ。いいかい、%1$sだよ。分かったら返事をするんだ、%1$s!!', $newName);
        $you->changeName($newName);
    }

    // 入力文字列からランダムに一文字を選択する
    private static function _pickOneCharacter(string $str): string
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        $randomIndex = random_int(0, mb_strlen($str) - 1);
        return mb_substr($str, $randomIndex, 1);
    }
}

あなたクラス

作中で言うところの千尋を表すデータクラスです。名前のみを持ちます。
ゲッター、セッター、コンストラクターなどの機械的なコードは省略します。

class You
{
    private string $_name;

    public function changeName(string $name): void
    {
        $this->_name = $name;
    }

    // 契約書を受け取り署名する
    public function signContract(Contract $contract): void
    {
        $contract->sign($this->_name);
    }
}

実行例

$ make run
契約書だよ。そこに名前を書きな。
山田太郎
フン。山田太郎というのかい。贅沢な名だねぇ。
今からお前の名前は太だ。いいかい、太だよ。分かったら返事をするんだ、太!!

名前を何も入力せずに実行すると...

湯婆婆がクラッシュします。(元ネタを再現)

$ make run
契約書だよ。そこに名前を書きな。

フン。というのかい。贅沢な名だねぇ。
Fatal error: Uncaught Error: Minimum value must be less than or equal to the maximum value in /app/src/Yubaba.php:40
Stack trace:
#0 /app/src/Yubaba.php(40): random_int(0, -1)

ソースコード

GitHub に上げました。

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

PHPプロジェクトで導入すると便利そうなツール5選

はじめに

PHPプロジェクトで導入すると便利そうなツールをまとめてみました。

自動テスト

PHPUnit

PHPでの単体テストと言えばPHPUnitが最も有名かと思います。
やり方についてはググればいくらでもでてきますので、ここでは個人的所感を書いていきます。

手動テストが不要になるわけではない

自動テストを頑張って書いていればある程度の動作保証にはなると思いますが、それによって手動テストが完全に必要なくなるかと言われればそうはならないと思っています。

ただ凡ミスは防げる

リファクタリング時にテストを実施した際に「あ、やべここ壊れれてた。危ない危ない。」というのは何回かありました。

複雑なパターンの検証には便利

少しずつ条件を変えてテストしなければならない箇所には、自動テストがかなり力を発揮してくれるかと思います。

テスタビリティの高いコードはいいコード

これが大きいメリットかなと個人的には思っています。
魔のメソッドを生み出してしまった際これどうやってテストコードに落とし込むの?と自問自答してしまうことがありました。
単一責任の原則から乖離したメソッドは、テストがしづらいです。逆に言うとテスタビリティの高いコードというのは責務が明確になっています。これは仕様変更などの際に影響範囲が明確になり、対応が行いやすくなります。

自動テストは手動テストの代替手段とだけ考えていましたが、実際には設計にも役立ちました。
また、カバレッジレポートの出力を行えばデッドコードや不要な引数などもひと目でわかるようになりますので、コードの品質維持にもつながっていきます。

デバッグ手法

XDebug

「XDebug」は、PHPのデバッグ用の拡張モジュールになります。

プロファイリングツールとして処理が遅い部分を突き止めてくれたりもするらしいですが、私はバグ調査時などに重宝しています。

ステップ実行は神です。延々と変数をログに吐き出していた頃が懐かしいです。教えてくれたチームメンバーありがとう。
PHPで開発する際は必須なツールかと思います。私はもう手放せません。

ボトルネック調査(プロファイリング)

Blackfire

実効効率を改善する場合に用いられるプロファイリングツールです。
私自身まだ使ったことはないのですが、PHPでのプロファイリングツールで調べるとXDebugとBlackfireの記事がよくでてきたので、機会があれば使ってみたいと思います。

バグの事前検知

phpmd

PHPの静的解析ツールになります。
潜在的なバグになりそうな部分や実装上の問題を検出してくれるツールです。

マニュアルの自動生成

PHPDocumentor

PHPDocやタイプヒンティングが書いてあるコードであればそれを元に自動でドキュメントを生成してくれるツールです。
生成されたドキュメントよりも、これがあることにより、PHPDocなどが適切に書かれることになりチーム開発での品質維持に繋がりそうだなと思いました。個人でやるというよりは、チームとして取り決めて使っていく方がよさそうです。

まとめ

エンジニアなりたての頃(まだペーペーですが)はとりあえず動けばよしという感じだったのですが、運用や保守を経験していくうちに過去の自分に苦しめられることが何度もありました。そして今の自分も未来の誰かを苦しめる可能性が常に存在しています。その可能性を少しでも減らすために、ツールの力も借りつつテスタビリティが高いコードを書いたり、ドキュメントを残したりとできることはやっていかなければならないなと思っています。
また、バグ調査時などもツールを駆使して早期解決に役立てたいなと思いました。

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

VSCode の php-cs-fixer で使っている設定

このページについて

PHP を VSCode を使用して開発する事がことが多く、
現場が変わる度に設定を調べ直すのが面倒だったので、ここにメモがわりに書くことにする。

settings.json
  "php-cs-fixer.onsave": true,
  "php-cs-fixer.executablePath": "${extensionPath}/php-cs-fixer.phar",
  "php-cs-fixer.lastDownload": 999999999999999,
  "php-cs-fixer.rules": {
    "@PSR2": true, // PSR-2 Coding Style Guide に即した形式にフォーマットする
    "no_unused_imports": true, // 使用していない use 句を削除する
    // "ordered_imports": true, // use 句をアルファベット順にソートする
    "array_syntax": { "syntax": "short" }, // 配列の定義方法を短縮形(例: $hoge = [];)にする
    "single_quote": true
  },
  "[php]": {
    "editor.defaultFormatter": "junstyle.php-cs-fixer"
  },
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む