20210305のPHPに関する記事は12件です。

久しぶりにLaravel触ろうとしてすっかり忘れてた [Mac]

久しぶりにLaravel触ろうとしてすっかり忘れてたので入力コマンドを一覧にしてみた

※諸事情によりLaravel6系でやります。
Laravelのサポートについてはこちらの方が詳しく説明されています。

目次

  • composerが入っているかの確認
  • composerでlaravelインストール
  • バージョンを指定してプロジェクトを作成
  • laravelの起動を確認
  • MySQLの設定
  • SQLiteの場合
  • laravel日本語化

composerが入っているかの確認

composer
composer -v

開発環境の構築が必要な場合

Homebrewインストール

Homebrew~composer
# Homebrewインストール
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# composerインストールと確認
brew install composer
composer

composerでlaravelインストール

composer-laravel
composer global require "laravel/installer"

バージョンを指定してプロジェクトを作成

composer-laravel
composer create-project laravel/laravel "プロジェクト名" 6.* --prefer-dist

laravelの起動を確認

※ポートは任意。なくても良い

laravel
cd "プロジェクト名"
php artisan serve --port=8080

http://127.0.0.1:8080にアクセス

MySQLの設定

MySQL
mysql.server start
mysql -u root -p
# パスを聞かれるがそのまま[enter]
MySQLデータベース作成、パスワード設定
create database 'データベース名';
show databases;
use 'データベース名';
update mysql.user set password=password('パスワード') where user='root';
flush privileges;
exit;
MySQL再起動
mysql.server stop
mysql.server start

.envファイル変更

.env修正
DB_CONNECTION=mysql
DB_HOST=localhost //修正
DB_PORT=3306
DB_DATABASE='データベース名' //修正
DB_USERNAME=root
DB_PASSWORD='パスワード' //修正

SQLiteの場合

.env修正
DB_CONNECTION=sqlite //変更
// DB_DATABASE='データベース名' //コメントアウト
databaseディレクトリにファイル作成
cd "プロジェクト名"/database
touch database/database.sqlite

laravel日本語化

config/app.phpの修正

app.phpの修正
'timezone' => 'Asia/Tokyo',// タイムゾーン
'locale' => 'ja',          // 第一言語を日本語(ローカライゼーション)
'fallback_locale' => 'en', // 該当言語が見つからない場合の言語
'faker_locale' => 'ja_JP',

ここまでで、laravel初期設定は完了です。

参考

https://qiita.com/park-jh/items/78efe8c3c93cf533aafa
https://qiita.com/S-Masakatsu/items/b231a8a02737aff6a808

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

PHPの型宣言は型の変換を行う

POST送信される値は全て文字列(Stirng型)として受け取ります。
そのため、下記のような関数を実行する場合、都度int型にキャストする必要があると思っていました。

function plusOne(int $num)
{
   return $num + 1;
}
$num = $_POST['num'];//"1"が送られてきたとする
$res = plusOne( (int)$num );

var_dump($res);//2が表示される

ただ実際にはキャストをしなくても型エラーを吐きません。

$num = $_POST['num'];//"1"が送られてきたとする
$res = plusOne( $num );

var_dump($res);//エラーにならない

なぜかと思ったのですが、どうやらPHPの型宣言は可能な限り暗黙の型変換を行うためにこういったことが起きるようです。
つまり、上記のコードはString型の"1"をint型の1に変換してplusOne()関数を実行しています。

個人的にはラクで良いやと思うのですが、これでは型宣言を行う意味が少しぼやけてしまう気もします。
もっとカタい言語の経験がある人からしたら「なんじゃこりゃ」という仕様かもしれません。
そういった方はdeclare文でstrictモードを有効にしましょう。
そうすれば厳密な型宣言が可能になります。

<?php
declare(strict_types=1);

ここまで全てドキュメントに書いてある内容ですが、最近まで知らずに驚いたことなので記事にしました。

おまけ
実際には数字を全てint型に変換するラッパー関数を噛ませるのが良さそうですね。

    function exePlusOne(int $num)
    {
        return $num + 1;
    }

    function plusOne($num)
    {
        if(preg_match("/\A[0-9]+\z/",$num) !== 1) return 0;
        return exePlusOne((int)$num);
    }

    var_dump(plusOne('1'));

以上

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

PHP 配列の扱い、foreachについて

PHPの配列についてのメモ


$arr = ['算数','国語','社会'];
// var_dump($arr);
// $arr['理系'] = '政治';

// var_dump($arr);
$arr[]= 'hoge';//インデックスに追加出来るpushみたいな感じ
// var_dump($arr);

foreach($arr as $key){//出力:算数国語社会hoge
  echo $key;
}

foreach($arr as $key =>$value){//出力:{0算数1国語2社会3hoge
  echo $key;
  echo $value;
}

foreach($arr as $key =>$value){//出力:{0123
  echo $key;
}

上記の説明

配列は$arr = [];$arr = ['算数','国語','社会'];のように定義した後
$arr[] = 'hoge';とするとJSでいうpushしたようにインデックスの3番目にhogeを入れられる。

forecachの説明

配列のkeyを設定している時はforeach($arr as $key =>$value){}の$keyでキーの値を出力し、valueで値を出力出来る。
$valueを設定しない場合asの後に設定した変数で($key)で値を出力出来る。

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

Laravel はじめました [1. 環境構築]

Java エンジニアですが仕事で使うので Laravel を勉強してみました。

要件

  • PHP 5.6
  • Laravel 3
  • MySQL 5.7
  • Apache 2.4

開発環境

  • macOS Big Sur
  • VSCode

ローカル環境構築

  • mac に php 5.6 をインストール

    $ brew install php@5.6
    
    • 上記でいけると思ったら、Homebrew で php 5.6 のサポートは切れているとのこと
    • サードパーティ製のリポジトリからインストールした

      $ brew tap exolnet/homebrew-deprecated
      $ brew install php@5.6
      
  • VSCode に 以下プラグインを追加

    • Laravel Artisan
    • Laravel Brade Snippets
    • Laravel goto view
    • Laravel Snippets
    • PHP Debug
    • PHP IntelliSense
  • ローカル PC に PHP をインストールするつもりはない

リモート環境構築

どうせなら docker 上で動かそうと思い、 github をウロウロしました。
かなり素晴らしいリポジトリを発見したので、 fork させていただきました。

  • sosobl/env-laravel

  • 構成

    • app
      • php と apache が稼働するコンテナ
    • db
      • MySQL が稼働するコンテナ
      • 一応コンテナを落としても中身は残るようにしてある
  • 使い方

    • 初回 (Laravel プロジェクトを作成する)

      $ git clone git@github.com:sosobl/env-laravel.git
      $ cd env-laravel
      $ make create-project # Install the latest Laravel project
      $ make install-recommend-packages # Not required
      
    • 2 回目以降 (docker コンテナだけ起動する)

      $ git clone git@github.com:sosobl/env-laravel.git
      $ cd env-laravel
      $ git clone git@github.com:laravel/laravel.git docker-laravel/backend # Clone any project to the backend directory
      $ make init
      
  • 説明は割愛します

    • 一応自分なりに理解できるまでソースは読みました
    • が、説明を記述するほどの余力は残りませんでした
    • fork 元よりステップ数は減っているので、お暇があれば読んでみてくだちい

改善点

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

PHPのクラスの基本と継承(+α)についての概説

「継承がいまいち分からない」というリクエストがあり実施した社内研修用の資料を共有します。

対象:いわゆるコーダー、CMSのテンプレートや簡易なカスタマイズはできる
解説範囲:concrete5 CMS で頻出する範囲

なぜクラスという仕組みがあるのか

クラスの説明のために「そもそもオブジェクト指向とは何か」から始める解説がよくありますが、今回はそこは省きます。それは例えばスマホ決済の説明のために「そもそも貨幣とは何か」から説明を始める様なものだからです。
多くの人は、貨幣経済がなぜ生まれどういう意味があるのか、など理解してなくても、便利だから、みんなが使っているから、という理由でお金を使うでしょう。お金とは便利なもので、スマホ決済はさらにめっちゃ便利なもの。そういう理解で実際には事足ります。

クラスもそういうもので、そもそもプログラミング自体がソフトウェアを作れる便利な代物で、クラスはプログラミングのためのめっちゃ便利なツール、そういう感じです。もちろん、オブジェクト指向が生まれた歴史を調べると面白いと思いますが、ある程度使いこなしてからの方が実感も湧くでしょう。

ではクラスはなぜ便利なのか。ひとことで言うと、人間の脳が高性能ではないから、と言うことに尽きます。

仮に、ソフトウェアが何十万行もの一つのPHPファイルに書いてあったとしましょう(決してこの行数は誇張ではありません。例えば concrete5は5000以上のPHPファイルで構成されています が、それぞれに100行のプログラムがあったら50万行です)。
もちろん、それで動かないと言うことはないのですが、「冒頭に書かれたこの変数の内容を変更した時に、どこまで影響があるんだろう」「この関数にバグがあって修正したいんだけど、副作用で別の場所にバグが起こったらどうしよう?」「どうもこの関数でエラーが起きてるっぽいけど、中身はどこに書いてあるんだろう?」

大きなファイルの弊害

何十万行のプログラムが全て頭に入っていて、それらの疑問に即座に答えを出せる人はまずいませんよね。一度に把握できる程度の適切な量にプログラムを分割できること、それがクラスと言う仕組みの便利なところです。

言い換えれば、良いプログラムとは「人間にやさしいプログラム」とも言えます。なるべく「ここを変えても壊れないかな?」「こう言う時はどうなるんだろう。エラーになったら嫌だな」と言った心配事をなくすことが重要です。

基本的なクラス

と言うことで、クラスの基本機能は「プログラム全体から関連する変数と関数を切り出してひとまとまりにすること」です。そのひとまとまりに名前をつけることができるのがクラスといえます。

下記の例では「BasicClass」と言う名前になっています。そして、クラスの中に入れると変数が「プロパティ」関数が「メソッド」と言う名前に変わりますが、基本的には同じものだと思ってOKです。

<?php
class BasicClass
{
    // プロパティの宣言
    public $var;

    // メソッドの宣言
    public function getVar() {
        // プロパティには $this->プロパティ名 でアクセスできる
        return $this->var;
    }
}

このクラスは、1つのPHPファイルにいくつでも書くことができますので、何十万行のPHPファイルに数千個のクラスが書いてある、と言うことも仕様上はできてしまいます。しかし、せっかくプログラムを分割してわかりやすくしたのですから、ついでにファイルも別にした方がいいですよね。と言うことで、コーディング規約上で1ファイルにクラスはひとつ、と定められていることが多いです。

インスタンス

また、「クラスは設計図のようなもの」と言う説明も聞いたことがあるでしょう。
設計図を使って実体を作成し、それぞれ別の情報をもったモノとして扱うことができます。
これをインスタンスとも呼びます。

// インスタンスを作成
$a = new BasicClass();
// プロパティ $var に文字を代入
$a->var = 'Apple';

$b = new BasicClass();
$b->var = 'Banana';

echo $a->getVar(); // Apple
echo $b->getVar(); // Banana

名前空間

プログラムをクラスで整理することにしたとしても、クラスが何百個もあったら、やっぱり把握するのが大変そうです。そこで、フォルダで整理できるようにしたのが名前空間という仕組みです。 namespace というキーワードで、フォルダ名を書くというイメージです。パソコンのフォルダの仕組みと同様、同じ名前空間内に同じ名前のクラスを複数定義することはできませんが、名前空間が違えば同じ名前のクラスを作成することができます。

<?php

namespace Vendor\Package\Apple;

class BasicClass()
{
}
<?php

namespace Vendor\Package\Banana;

use Vendor\Package\Apple\BasicClass as Apple;

class BasicClass()
{
    public function getApple()
    {
        // 他の名前空間のクラスは、名前空間を含むフルネームで指定するか、
        // use キーワードで読み込むことで使えます。
        // as キーワードでエイリアス指定することで、短い別名を指定することもできます。
        return new Apple();
    }
}
$a = new \Vendor\Package\Apple\BasicClass;
$b = new \Vendor\Package\Banana\BasicClass;

この名前空間は、PHPファイルそれ自身が入っているフォルダとは関係がありません。そのため、名前空間が \Apple で入っているフォルダが /Banana ということも可能です。しかし、せっかくPHPファイルをフォルダ分けして整理するための仕組みなのですから、実際のPHPファイルそれ自身も、同じ名前のフォルダに入れて整理するのが一般的です。

アクセス権

クラスを使っても、実際にはクラスの外部から、内部のプロパティに影響を与えることができてしまいます。上の例がまさに、クラス内のプロパティ $var の値を変更しています。これでは当初の目的が達成できませんので、プロパティやメソッドはアクセス権を定義することができ、外部からの参照を拒否することができます。

<?php

class PrivateClass
{
    // クラス内部からしかアクセスできない
    protected $var;
}

$a = new PrivateClass();
$a->var = 'Apple'; // PHP Fatal error

このように、外からアクセスされてもいいもの、されたら困るもの、を分けることで、できるだけ副作用の少ない、安心安全なプログラムを作っていくことができます。

static

プロパティやメソッドを static キーワードをつけて定義することで、インスタンスを作成せずにアクセス可能になります。静的(static)プロパティやメソッドにアクセスするには、矢印 -> ではなくダブルコロン :: を使用します。

<?php

class StaticSample
{
    public static $message = 'Hello World!';

    public static function displayHelloWorld()
    {
        echo self::$message;
    }
}
StaticSample::displayHelloWorld(); // Hello World!

インスタンスを作成しないので、状態に関わらず常に同じ処理を行うという場合に使われます。

は安心安全なプログラミングに不可欠なものです。クラスを利用するときに、いちいちこんなチェックをしなきゃならない、それを忘れたためにエラーが起こる、と言われたら、誰だってめんどくさ!って思うでしょう。

$obj = new BadClass();
$result = $obj->getResult();
// nullでもなく、かつ文字列かどうかをいちいちチェックしてから表示…めんどっ
if ($result !== null && is_string($result)) {
    echo $result;
}

クラスのメソッドは、引数にどんな型を受け入れるのか、返り値はどんな型になるのかを強制することができます。強制することで、いざ利用するときは余計な心配をしなくて済みますね。

<?php
class Foo
{
    protected $bar;
    protected $number = 0;
    protected $string;

    // 数値のみ受け付けます。
    public function setNumber(int $number)
    {
        $this->number = $number;
    }

    // メソッドの返り値の型を強制できます。
    public function getNumber(): int
    {
        return $this->number;
    }

    // 何も返さないという特殊な型指定 void も可能です。
    public function setString(string $string): void
    {
        $this->string = $string;
    }

    // null または string 型
    public function getString(): ?string
    {
        return $this->string;
    }

    // クラス名を指定することもできます。
    public function setBar(Bar $bar): void
    {
        $this->bar = $bar;
    }

    public function getBar(): ?Bar
    {
        return $this->bar;
    }
}

PHP 7.4 以降では、プロパティに型宣言を含めることができます。

<?php
// https://www.php.net/manual/ja/language.oop5.properties.php#example-208 から引用
class User
{
    public int $id;
    public ?string $name;

    public function __construct(int $id, ?string $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}

$user = new User(1234, null);

継承

次に、クラスの便利な仕組みである継承と、継承に似ているけど異なる機能について紹介します。

クラスを宣言する際に、続けて extends キーワードを使って、他のクラスを継承することができます。継承とは、かんたんにいえば、他のクラスをもとに一部を改造したクラスを作成できる機能です。

まず、下記のようなクラスがあったとします。

<?php

class BaseClass
{
    protected $var;

    // コンストラクタは、new キーワードでクラスのインスタンスを作成する際に呼ばれる特殊なメソッド。
    public function __construct($var)
    {
        $this->var = $var;
    }

    public function getVar()
    {
        return $this->var;
    }
}

extend を使って、この BaseClass をもとに改造クラスを作りましょう。

<?php
// BaseClass を継承して作成
class ExtendClass extends BaseClass
{
    public function getVar()
    {
        return $this->var . '!!!';
    }
}

実際に使ってみましょう。

$b = new BaseClass('Apple');
$e = new ExtendClass('Apple');

echo $b->getVar(); // Apple
echo $e->getVar(); // Apple!!!

ExtendClass の方では、 getVar() メソッドしか定義していないのに、 BaseClass と同じようにコンストラクタに値を渡したり、プロパティの値を取得することができました。このように、書いてないものは継承元のクラスのまま、という形になります。

しかし、改造できるのは便利ですが、魔改造されるのも困りものですよね。そこで、継承で改造できる範囲とできない範囲を明確にすることができます。

<?php

class BaseClass
{
    // アクセス権で private を指定すると、継承したクラスからは触れなくなります。
    private $foo = 'foo';
    // protected では、継承したクラスからは触れますが、外部からは触れません。
    protected $bar = 'bar';
    // public は継承できますし、外部からもアクセスできます。
    public $baz = 'baz';

    // 継承したクラスから呼べなくなります。
    private function getFoo()
    {
        return $this->foo;
    }

    // 継承したクラスから呼べます。
    protected function getBar()
    {
        return $this->bar;
    }

    // 継承したクラスと外部から呼べます。
    public function getBaz()
    {
        return $this->baz;
    }
}

class ExtendClass extends BaseClass
{
    public function getPrivateProperty()
    {
        // エラーになります。
        return $this->foo;
    }

    public function getProtectedProperty()
    {
        // 動きます。
        return $this->bar;
    }

    public function getPublicProperty()
    {
        // 動きます。
        return $this->bar;
    }

    public function callPrivateMethod()
    {
        // エラーになります。
        return $this->getFoo();
    }

    public function callProtectedMethod()
    {
        // 動きます。
        return $this->getBar();
    }

    public function callPublicMethod()
    {
        // 動きます。
        return $this->getBaz();
    }
}

抽象クラスと抽象メソッド

設計時点で、そもそも継承によって色々なクラスのバリエーションを作ることを想定しておきたい場合に使われるのが abstract キーワードです。

<?php

abstract class AbstractClass
{
    // このクラスを継承したクラスは、必ずこのメソッドを実装する必要があります。
    abstract protected function getValue();

    // このクラスを継承したクラスは全て、このメソッドが利用できます。
    public function displayValue() {
        echo $this->getValue();
    }
}

abstract キーワードをつけた抽象クラスは、インスタンスを作成することができません。

$obj = new AbstractClass(); // エラーになります

また、 abstract キーワードをつけたメソッドは、継承したクラスで必ず実装する必要があります。

<?php

class ExtendClass extends AbstractClass
{
}

$obj = new ExtendClass(); // getValue() を実装していないのでエラーになります

このように制限を設けることで、同じ抽象クラスを継承したクラスたちの挙動をある程度共通かことができますので、兄弟として似たような使い勝手で使うことができます。

インターフェース

抽象クラスは便利ですが、制限もあります。それは、クラスは複数のクラスを継承できないということです。この制限は初学者には実感しづらいと思いますが、設計しだすと結構困ります。

そこで、「特定のメソッドの実装を強制する」という抽象メソッドの機能のみを取り出して、複数継承できるようにしたのがインターフェースです。

<?php

interface NameInterface
{
    public function getName();
}

interface DescriptionInterface
{
    public function getDescription();
}

// インターフェースの場合は extends ではなく implements を使います。
class ExampleClass implements NameInterface, DescriptionInterface
{
    public function getName()
    {
        return 'Example';
    }

    public function getDescription()
    {
        return 'This is an example class';
    }
}

気軽に複数指定できるという特徴を活かして、複数のクラスをカテゴリー分けするのに使うこともあります。

$obj = new ExampleClass();
if ($obj instanceof NameInterface) {
    echo 'This class implements NameInterface';
}

トレイト

抽象メソッドも便利なものですが、複数のクラスで似たようなメソッドを使い回すという用途に使うには、複数のクラスを継承できないという制約がやはり邪魔になってきます。そのような時のために、特定のプロパティやメソッドを使い回すための仕組みがトレイトです。Sassでいうmixinみたいな感じです。

<?php

trait NameTrait
{
    protected $name;

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

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

class Foo
{
    use NameTrait;
}

$foo = new Foo();
$foo->setName('Apple');
echo $foo->getName(); // Apple

質疑応答

concrete5 で Page や \Page という表記が色々あるのはなぜ?

concrete5 でページを表現するクラスは、名前空間を含めたフルネームでは \Concrete\Core\Page\Page です。このクラスには エイリアス が設定されており、 \Page という短いクラス名でも使えるようになっています。

次に、テンプレートファイルは特に名前空間が宣言されていないため、フルネームじゃなくてもこのクラスを呼ぶことができます。

<?php
namespace Foo;

// こう書くと、宣言されている名前空間が適用されるので
// \Foo\Page というクラスを呼び出したことになります。
$c = new Page();

// バックスラッシュから始めると、フルネームでクラスを呼び出したことになります。
$c = new \Page();

// エイリアスはクラスの別名を定義するものなので、上の呼び出しと下の呼び出しは結果は全く同じです。
$c = new \Concrete\Core\Page\Page();
<?php
// 名前空間が宣言されていないPHPファイル内では、次の2つは全く同じです。
$c = new Page();
$c = new \Page();

名前空間は見た目はとっつきにくいですが、フォルダと同じと考えれば、CSSから画像を呼び出すのと同じです。

/* 絶対パスで書く場合はスラッシュではじめますし */
background-image: url(/asset/images/example.png);
/* 相対パスで書くこともありますよね。名前空間も同じような仕組みです */
background-image: url(../images/example.png);

extends と implements は同時に使える?

使えます!

<?php

namespace Concrete\Core\Page;

use Concrete\Core\Attribute\ObjectInterface as AttributeObjectInterface;

use Concrete\Core\Export\ExportableInterface;
use Concrete\Core\Permission\AssignableObjectInterface;
use Concrete\Core\Permission\AssignableObjectTrait;
use Concrete\Core\Site\SiteAggregateInterface;
use Concrete\Core\Site\Tree\TreeInterface;
use Concrete\Core\Summary\Category\CategoryMemberInterface;

class Page extends Collection implements CategoryMemberInterface,
    \Concrete\Core\Permission\ObjectInterface,
    AttributeObjectInterface,
    AssignableObjectInterface,
    TreeInterface,
    SiteAggregateInterface,
    ExportableInterface
{
    use AssignableObjectTrait;
...

extends で孫は作れる?

作れます!

<?php

class MyClass
{
}

class ChildClass extends MyClass
{
}

class GrandChildClass extends ChildClass
{
}

trait で private は使える?

使えます!トレイトはあくまで一部のメソッドやプロパティを「そのクラス自身の一部として読み込む」挙動になりますので、親だったり子だったりといった関係性からは独立したものになっています。

オブジェクト指向の考えから派生して生まれた継承という仕組みですが、その便利なポイントが実は、複数のクラスで共通点を作れるというところだった。この共通点を作るのに実は親子のような関係性は不要だしむしろ邪魔、ということが、インターフェースやトレイトが生まれた背景なんでしょうね。

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

【Laravel】Seedデータファイルを作るコマンド

php artisan make:seeder UserTableSeeder

USerTableSeeder.phpファイルをつくることができる。

<?php

use Illuminate\Database\Seeder;

class USerTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}

コマンドで作られたファイルの中身はこのような記述になっている.

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

ext-zipのバージョンを確認する

目的

  • ext-zipのバージョンを確認する方法をメモ的にまとめる

方法

  1. 下記コマンドを実行する。

    $ php --ri 'zip'
    
  2. 「Zip version =>」の後に記載されている値がバージョンである。

参考文献

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

Laravelについての認識

Laravelのインストール場所

今まではPC本体にLaravelをインストールするものだと考えていましたが、Laravelinstallerを用いて作成したプロジェクト自体にLaravelが存在するらしい。

つまりWord等のソフトウェアとしてインストールするわけではない。

Laravelを利用する = Laravelinstallerを用いてLaravelの組み込まれたプロジェクトを作る

Laravelinstaller ≒ Laravel

的な感じ?

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

EC-CUBE4 プラグイン開発 PluginManager の状況別実行関数

EC-CUBE4 プラグイン開発では、 PluginManager でプラグインのインストールや有効時の処理を記述します。
管理している状態は以下の4つです。

  • install (インストール時の処理)
  • uninstall (アンインストール時の処理)
  • enable (有効化時の処理)
  • disable (無効化時の処理)

インストールを行った時にはもちろん、install( ) が実行されるわけですが、例えば、 有効時にアンインストールした場合 と 無効時にアンインストールした場合 は、どのような挙動を取るのでしょうか?

以下にまとめました。

実行コマンド

EC-CUBEに実装されている、開発用のプラグイン操作コマンドを使用しました。

bin/console eccube:plugin:install
bin/console eccube:plugin:uninstall
bin/console eccube:plugin:enable
bin/console eccube:plugin:disable
bin/console eccube:plugin:update

状態別実行関数とその順序

順番に実行される関数を表記します。

インストール時
install()
のみ
有効化時
enable()
のみ
無効化時
disable()
のみ
無効化状態からアンインストール
uninstall()
のみ
有効化状態からアンインストール
disable()
からの
uninstall()
有効化状態からアップデート
update()
のみ
無効化状態からのアップデート
update()
のみ

問題になりそうなのは、アップデート時の挙動です。
有効・無効どちらの状態でも、 update() しか呼ばれないため、 無効状態でフラグを false にし有効では true といった新機能を実装した場合、プラグインの今の状態がなにかを判定しないと、意図しない挙動となる可能性がありそうです。

例えば

public function enable()
{
  // データベースの特定レコードのフィールドを true にする処理
}

public function disable()
{
  // データベースの特定レコードのフィールドを false にする処理
}

public function update()
{
  // データベースの特定レコードのフィールドを false にする処理
}

この場合、有効時に利用者がプラグインをアップデートすると、フィールドの値は false になってしまいます。

個人的には

この挙動から、有効時の update( ) 時では、
disable( )を実行してから、update( )を実行し、 enable( )が実行される という挙動の方が、開発側の負担は少ないのかなと感じました。
動作的にも、 disable( ) の実行時には、破壊的な処理は行わないと思いますので。
```

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

PHPUnitでHTMLコードガバレッジを出すまで(Docker使用)

はじめに

以下記事の【phpunitを少し使ってみる】までは行っている前提で話します。

最終的表示までのものgithubにあげているのでもしよかったら見てください。
どこに何を書けばいいかもここのファイル等見てもらった方が早いかもです。

最終的な見た目は以下のような感じです。

スクリーンショット 2021-03-04 23.20.21.png
スクリーンショット 2021-03-04 23.20.33.png

上記の【phpunitさわるまで】以降にすること箇条書き

※HTMLでコードガバレッジを表示するのに必要な設定

  • 【step1】 tokenizer(拡張モジュール)追加
  • 【step2】 Xdebug(拡張モジュール)追加
  • 【step3】 php.iniの設定、反映(Xdebug(拡張モジュール)有効化)
  • 【step4】 phpunit.xml(コードガバレッジ出力のための設定ファイル的なもの)の作成
  • 【step5】 メソッドの修正
  • 【step6】 最後に出力コマンド

【step1】 tokenizer(拡張モジュール)追加

Dockerfileに以下追記
※ですがもしかしたらこれいらないかもしれないです、、すでに入ってる的なログ出てた気がするので念のため書いておきます、、

Dockerfile
RUN docker-php-ext-install tokenizer

【step2】 Xdebug(拡張モジュール)追加

Dockerfileに以下追記。すでに記述してある処理はそのままで。
ちなみに『apt-get』使用でインストール出来なかったのでこのインストールの方法で行っています。
peclのインストールがwget
インストールしたpeclでxdebugをインストールするという感じです。

インストール方法は以下の記述参考
https://pear.php.net/manual/en/installation.getting.php

peclでインストールできるもの以下
https://pecl.php.net/package-stats.php

Dockerfile
RUN apt-get update \
&& apt-get install -y \
wget

# コードジェネレーターで必要
RUN pecl install xdebug

【step3】 php.iniの設定、反映(Xdebug(拡張モジュール)有効化)

xdebug使えるようにするためphp.iniを自分で作成してDockerの環境に反映するをしました。

ちなみにextension=xdebug.soの記述書け!は以下リンク先に書かれていたもので
http://xdebug.org/docs/install

xdebug.mode=coverageの記述書け!は失敗ログで言われたものです。

Warning:       XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set

Dockerfileに以下追記

Dockerfile
COPY html/php.ini /usr/local/etc/php/conf.d

php.iniを以下場所に作成

html/php.ini
extension=xdebug.so

xdebug.mode=coverage

【step4】 phpunit.xml(コードガバレッジ出力のための設定ファイル的なもの)の作成

:sun_with_face:『docker-compose.yml』ある場所で$ docker-compose up --build -dを叩きます。

:sun_with_face:以下コマンド今使用しているコンテナIDの確認を行う
$ docker ps

:sun_with_face:コンテナ内に以下コマンドで入る、 ※『1999d283b4f9』は上記で出力したコンテナIDを使用してください
$ docker exec -i -t 1999d283b4f9 bash

:sun_with_face:phpunit.xmlの作成コマンドを打つ、そして聞かれた内容に答えていく

$ vendor/bin/phpunit --generate-configuration

【step5】 メソッドの修正

テストメソッド上の何のテストをするかを記述(@coversの部分)
これないとThis test does not have a @covers annotation but is expected to have oneと言われます。

    /**
     *  @covers sample\Sample::a
     **/
    public function testA()

全体
https://github.com/sachiko-kame/samplePHPTest/blob/main/html/TEST/SampleTest.php

【step6】 最後に出力コマンド

これで『TestResult』フォルダ内に無事index.htm等々作成出来て表示に問題がなければOKです!
うまくいかない場合『phpunit.xml』が同じでない可能性が高いと思うので以下と見合わせていただければと思います。
https://github.com/sachiko-kame/samplePHPTest/blob/main/html/phpunit.xml

$ vendor/bin/phpunit --coverage-html TestResult

参考

https://tech-blog.rakus.co.jp/entry/20200908/docker
https://docs.docker.jp/engine/reference/builder.html#copy
その他所々にリンク貼ってます!

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

PHPUnitでHTMLコードカバレッジを出すまで(Docker使用)

はじめに

以下記事の【phpunitを少し使ってみる】までは行っている前提で話します。

最終的表示までのものgithubにあげているのでもしよかったら見てください。
どこに何を書けばいいかもここのファイル等見てもらった方が早いかもです。

最終的な見た目は以下のような感じです。

スクリーンショット 2021-03-04 23.20.21.png
スクリーンショット 2021-03-04 23.20.33.png

上記の【phpunitさわるまで】以降にすること箇条書き

※HTMLでコードカバレッジを表示するのに必要な設定

  • 【step1】 tokenizer(拡張モジュール)追加
  • 【step2】 Xdebug(拡張モジュール)追加
  • 【step3】 php.iniの設定、反映(Xdebug(拡張モジュール)有効化)
  • 【step4】 phpunit.xml(コードカバレッジ出力のための設定ファイル的なもの)の作成
  • 【step5】 メソッドの修正
  • 【step6】 最後に出力コマンド

【step1】 tokenizer(拡張モジュール)追加

Dockerfileに以下追記
※ですがもしかしたらこれいらないかもしれないです、、すでに入ってる的なログ出てた気がするので念のため書いておきます、、

Dockerfile
RUN docker-php-ext-install tokenizer

【step2】 Xdebug(拡張モジュール)追加

Dockerfileに以下追記。すでに記述してある処理はそのままで。
ちなみに『apt-get』使用でインストール出来なかったのでこのインストールの方法で行っています。
peclのインストールがwget
インストールしたpeclでxdebugをインストールするという感じです。

インストール方法は以下の記述参考
https://pear.php.net/manual/en/installation.getting.php

peclでインストールできるもの以下
https://pecl.php.net/package-stats.php

Dockerfile
RUN apt-get update \
&& apt-get install -y \
wget

# コードジェネレーターで必要
RUN pecl install xdebug

【step3】 php.iniの設定、反映(Xdebug(拡張モジュール)有効化)

xdebug使えるようにするためphp.iniを自分で作成してDockerの環境に反映するをしました。

ちなみにextension=xdebug.soの記述書け!は以下リンク先に書かれていたもので
http://xdebug.org/docs/install

xdebug.mode=coverageの記述書け!は失敗ログで言われたものです。

Warning:       XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set

Dockerfileに以下追記

Dockerfile
COPY html/php.ini /usr/local/etc/php/conf.d

php.iniを以下場所に作成

html/php.ini
extension=xdebug.so

xdebug.mode=coverage

【step4】 phpunit.xml(コードカバレッジ出力のための設定ファイル的なもの)の作成

:sun_with_face:『docker-compose.yml』ある場所で$ docker-compose up --build -dを叩きます。

:sun_with_face:以下コマンド今使用しているコンテナIDの確認を行う
$ docker ps

:sun_with_face:コンテナ内に以下コマンドで入る、 ※『1999d283b4f9』は上記で出力したコンテナIDを使用してください
$ docker exec -i -t 1999d283b4f9 bash

:sun_with_face:phpunit.xmlの作成コマンドを打つ、そして聞かれた内容に答えていく

$ vendor/bin/phpunit --generate-configuration

【step5】 メソッドの修正

テストメソッド上の何のテストをするかを記述(@coversの部分)
これないとThis test does not have a @covers annotation but is expected to have oneと言われます。

    /**
     *  @covers sample\Sample::a
     **/
    public function testA()

全体
https://github.com/sachiko-kame/samplePHPTest/blob/main/html/TEST/SampleTest.php

【step6】 最後に出力コマンド

これで『TestResult』フォルダ内に無事index.htm等々作成出来て表示に問題がなければOKです!
うまくいかない場合『phpunit.xml』が同じでない可能性が高いと思うので以下と見合わせていただければと思います。
https://github.com/sachiko-kame/samplePHPTest/blob/main/html/phpunit.xml

$ vendor/bin/phpunit --coverage-html TestResult

参考

https://tech-blog.rakus.co.jp/entry/20200908/docker
https://docs.docker.jp/engine/reference/builder.html#copy
その他所々にリンク貼ってます!

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

【初学者備忘録】2:プログラミングで使用する用語と意味

初学者備忘録2

備忘録2

昨日は直近で触れた用語や開発言語についてまとめました。
今日はプログラミングを勉強する中でよく聞くけど、あまり理解できていなかった用語についてまとめてみたいと思います。

用語まとめ

①エディタ
ソースコードやテキストなどを書くのに使うアプリ。
種類がたくさんあるので、ゆくゆくは種類なども把握していきたいと思います。
自分はプログラミングを始めた時に
Visual Studio codeを進めてもらって使用しています。

②UI
ユーザーインターフェース
利用者と製品やサービスの接点
レイアウト・画像・文字のフォント・メニューやボタンの操作性などユーザーが目にするもの・操作するものを指す

③GUI
グラフィカルユーザーインターフェース
マウスやタッチパネルなどで、画面を見ながら操作ができること
パソコン・スマートフォン・カーナビなどが該当する

④CUI
キャラクターユーザーインターフェース
キャラクターは英語で「文字」という意味
GUIとは逆にテキストデータのみで表示されるUI
ターミナルやコマンドプロンプトが該当する

⑤ディレクトリ
フォルダとほぼ同じ意味
GUIではフォルダ
CUIではディレクトリと呼ぶことが多い。
厳密には違う意味になるので、イコールではない
なぜ違う意味になるのかなどは別で調べて投稿できたらと思います。

⑥パス
日本語では「経路」という意味。
目的のフォルダに辿り着くための道順を表すときなどに使います。
ウェブサイトのアドレスもパスの一種。

  • 絶対パス
    • フルパスとも呼ばれる
    • ルートディレクトリから目的地までの経路
    • どのフォルダにいても常に同じスタートから同じ経路を辿る
  • 相対パス
    • 作業中のフォルダから目的のフォルダまでの経路
    • スタート地点が異なると経路も異なる

今日の一言

今日は熟練のプログラマーの方にとっては、当たり前のように使われているけれど
自分が独学で始めた時になかなか理解出来なかった用語に絞ってまとめてみました。
恥ずかしくて人に聞くこともできず、始めたてで何もわからなかった自分はとても苦労しました。
特にパスについては、まだまだ理解が追いついていない部分があるのでパスの勉強をしながら
自分の作業環境も整理していきたいと思います。
しばらくは用語や使ってみたツールなどを記録していきたいと思います。

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