PHP

提供:senooken JP Wiki
2024年4月5日 (金) 23:12時点におけるSenooken (トーク | 投稿記録)による版 (Library)

Library

Framework

  • Symfony
  • CakePHP
  • FuelPHP: 2010年誕生。
  • Codeigniter: シンプル、軽量。
  • Zend
  • Laravel: 2011年誕生。
  • Phalcon

Template

  • Blade
  • Smarty

ORM

  • Eloquent

Migrate

  • Phinx

Test

  • PHPUnit

Laravel

人気の理由

Laravelの人気を大検証 何が凄いの? | テクフリ

CakePHPのほうが早い。

  • 簡単にマスター可能
  • 自由度が高い

CakePHP

Basic

Structure

  • bin: cakeコマンド類。
  • config: CakePHPの全体設定にかかるファイル群。
  • logs
  • plugins
  • src
  • tests
  • tmp
  • vendor
  • webroot: アプリケーションルート。
Routing

Ref: ルーティング - 3.10.

config/routes.phpでルーティングの基本が設定される。ここのコードで、後述のMVCがある程度自動設定されている。

ほかに、アプリケーショントップの/アクセス時の処理を行う、重要な設定もここで行う。/はMVCの命名規則になっていないので、ここは手動設定?的なことが必要になる。基本はここがLoginになる。

Router::scopeとRouter::connectを使って処理する。

scopeはルーティングのグループ化。connectで個別に紐づける。

Router::scope('/blog', ['plugin' => 'Blog'], function ($routes) {
    $routes->connect('/', ['controller' => 'Articles']);
});

例えば、上記は/blogへのアクセスをArticlesController.index()に紐づける。

connectの第二引数にいろいろパラメーターを指定できて、actionのメソッドを指定できたりする。

Controller

AppControllerを継承して定義する。indexメソッドを最低限実装しておく。

XXXControllerのXXXの小文字部分がURLになっていて、これでアクセスするとindexが発動する。

メソッド名が、パスになっていて、それで表示される。このパスメソッドを一般的にacitonと呼んでいる。

$this->request

リクエストに関する情報が入っている。PHPの$_FILESとか$_POSTなどを使わなくも、これを使えばよくなる。

2次元配列にもなっているが、1次元配列部分はプロパティーとしてもアクセスできる。

  • params: 送信されたすべてが入っている。
  • data: POSTのボディー。
  • query: URLクエリー。
  • url
  • base
  • webroot
  • here:

特にdataをよく使うだろう。

View

Ref: ビュー - 3.10.

Controllerで表示もできるものの、Viewで表示部分をメインにすることもできる。

Viewはビューテンプレートとレイアウトで大きく構成される。

テンプレートは実際のページ表示用。レイアウトは、テンプレートを含み、ヘッダー、フッターなどをまとめている。

レイアウトを用意して、その中にビューテンプレートを埋め込んで表示するイメージ。これにより、ページ全体でレイアウトを統一しやすくなる。

テンプレートファイルのデフォルトの拡張子は.ctp (CakePHP Templateの略)。

Template

src/TemplateがViewテンプレート。ここにコントローラー名に対応したディレクトリーを作って、そこにViewテンプレートを作成する。

例えば、src/Template/Helloにindex.ctpを用意する。

Controller側で、public $autoRender = true;があると、テンプレートを使う。命名規則で自動的に。

そして、$this->viewBuilder()->autoLayout(false) でレイアウトの使用可否を設定する。

index.ctpはテンプレートなので、ここにPHPコードを記入してもOK。

テンプレート内では変数が使える。この変数は、コントローラーで$this->setで設定されたものになる。

基本的には以下のようなphpコードで埋め込む。

<?php echo $variable; ?>
<?= $variable ?>
Layout

デフォルトで使用するレイアウトは、src/Template/Layout/default.ctpにある。

ここにファイルを追加することが、レイアウトの作成になる。

レイアウト内で、テンプレートを表示する関数類がある。

  • $this->fetch('content'): ビューテンプレート

Controller側では、$this->viewBuilder()->layout('Hello');でレイアウトを指定できる。

Element

レイアウトよりも小さいパーツ。ボタンなど、流用するようなものをElementとして用意できる。

$this->element(エレメント名, [キー=>値,...])で表示できる。

src/Template/Element内に作成する。エレメント名.ctpで作成する。キー=>値の関係で、パラメーターを渡せる。

Controllerのaction内でsetで、layout内で使用する変数を指定できる。これで、layout-element間で変数を渡せる。

Model

DBを処理する部分。

具体的には、テーブルクラス (テーブルへのアクセス処理) とエンティティークラス (テーブルから取り出した1行分のデータのための列の表現) で実現する。

CakePHP内では、モデル名Table/モデル名でそれぞれ命名する。テーブルクラスは複数形、エンティティークラスは単数形で扱う。テーブル自体も複数形。

CakePHPでDBにアクセスする際には、まず設定ファイルにDBの情報を用意する。Config/app.phpのDatasourcesのdefaultに入力する。

モデル自体は、src/Model内に配置する。EntityとTableディレクトリーでそれぞれ用意する。

継承するだけで、基本的な動作は機能する。

Controllerから、これらのモデルにアクセスする。

DBへのアクセスにはORMのQueryBuilderとSQLベースのConnectionManagerがある。

ConnectionManager

SQLをそのまま発行するタイプのクラス。

$conn = ConnectionManager::get('設定名');
$result = $conn->execute('SQL');
TableRegistry

Ref: Saving Data - 3.10.

use Cake\ORM\TableRegistry;

// Prior to 3.6 use TableRegistry::get('Articles')
$articlesTable = TableRegistry::getTableLocator()->get('Articles');
$article = $articlesTable->get(12); // Return article with id 12

$article->title = 'CakePHP is THE best PHP framework!';
$articlesTable->save($article);

組み込まれていないテーブルはgetで取得する必要がある。

Migration

Ref:

PHPファイルでDBのスキーマ変更を行うための仕組み。VCSでDB設定を管理でき、コマンドでDBの設定などを行える利点がある。

CakePHPでは、Phinxをマイグレーションに使っており、コマンド類はPhinxのラッパーになっている。細かいことはPhinxにあたる必要がある。

config/Migrationsディレクトリーに、マイグレーションファイルを配置し、以下のmigrationsコマンドの実行でDBにテーブルを作成できる。

bin/cake migrations migrate
bin/cake migrations rollback

戻す場合はrollback。

マイグレーションファイルは、config/Migrationディレクトリーで、YYYYmmddHHMMSS_MigrationName.phpというように、作成日を入れて用意する。

自分で手作業でマイグレーションファイルを作成できるが、bakeコマンドでひな形を用意できる。これを使ったほうがおそらくいい。

マイグレーションファイル
Valid Column Types

Phinx で一般的に利用可能なフィールドの型は次の通り:

  • string
  • text
  • integer
  • biginteger
  • float
  • decimal
  • datetime
  • timestamp
  • time
  • date
  • binary
  • boolean
  • uuid

このほかに、以下も可能。

In addition, the MySQL adapter supports enum, set, blob, tinyblob, mediumblob, longblob, bit and json column types (json in MySQL 5.7 and above). When providing a limit value and using binary, varbinary or blob and its subtypes, the retained column type will be based on required length (see Limit Option and MySQL for details);

In addition, the Postgres adapter supports interval, json, jsonb, uuid, cidr, inet and macaddr column types (PostgreSQL 9.3 and above).

既存のテーブルにカラムを追加

以下のコマンドでカラム追加を含むコードを作成できる。

bin/cake bake migration AddPriceToProducts price:decimal
<?php
use Migrations\AbstractMigration;

class AddPriceToProducts extends AbstractMigration
{
    public function change()
    {
        $table = $this->table('products');
        $table->addColumn('price', 'decimal')
              ->update();
    }
}

addColumnの3引数にいろいろパラメーターを指定できる。

    public function change()
    {
        $table = $this->table('m_grade');
        $table->addColumn('image_data', 'blob', [
            'default' => null,
            'limit' => Phinx\Db\Adapter\MysqlAdapter::BLOB_MEDIUM,
            'null' => true,
            'after' => 'image_path',
        ]);
        $table->update();
    }

afterで直前の列を指定できる。

Blobの対応

CakePHP自体は、MySQLのblobには直接は対応していない。binaryでひな形を作って、手動でlimitを変更する。

列の更新

Updating columns name and using Table objects

If you use a CakePHP ORM Table object to manipulate values from your database along with renaming or removing a column, make sure you create a new instance of your Table object after the update() call. The Table object registry is cleared after an update() call in order to refresh the schema that is reflected and stored in the Table object upon instantiation.

https://book.cakephp.org/migrations/3/en/#updating-columns-name-and-using-table-objects

updateした後に、CakePHPのORMを使う模様。
         // Update exisiting column default row data from path.
        $mbaseTable = TableRegistry::get('m_base');
        foreach($mbaseTable->find() as $row) {
            $file_path = WWW_ROOT . $row->LOGO_PATH;
            if (is_readable($file_path)) {
                $raw_data = file_get_contents($file_path);
                if ($raw_data) {
                    $row->LOGO_DATA = $raw_data;
                    $mbaseTable->save($row);
                }
            }
        }

こういうイメージ。

Debug

Ref: デバッグ - 3.10.

CakePHP関係のクラスであればlogメソッドがある。

他に、Cake\Log\Log::write()のstaticメソッドもある。

Log::debug('text')などで使う。

  • pr: print_r+pre
  • debug:
  • dd: debug+die

Test

CakePHPはPHPUnitでのテストに対応している。

まずDBをテスト用に置換する。config/app.phpのDatasourcesにtestを追加しておく。

bakeコマンドの中で、fixtureとtestが関係するコマンド。

まずfixtureでテストデータを作成する。

bake fixture <model>

modelでMVCの一単位を指定する。

Error

PHP message: PHP Warning: file_put_contents(/var/www/html/logs/error.log) [<a href='http://php.net/function.file-put-contents'>function.file-put-contents</a>]: failed to open stream: Permission denied in /var/www/html/vendor/cakephp/cakephp/src/Log/Engine/FileLog.php on line 133

起動してトップ画面を開くと、logs/error.logに以下のエラー。

2024/04/04 07:27:48 [error] 30#30: *1 FastCGI sent in stderr: "PHP message: PHP Warning:  file_put_contents(/var/www/html/logs/error.log) [<a href='http://php.net/function.file-put-contents'>function.file-put-contents</a>]: failed to open stream: Permission denied in /var/www/html/vendor/cakephp/cakephp/src/Log/Engine/FileLog.php on line 133
PHP message: PHP Warning:  file_put_contents(/var/www/html/logs/error.log) [<a href='http://php.net/function.file-put-contents'>function.file-put-contents</a>]: failed to open stream: Permission denied in /var/www/html/vendor/cakephp/cakephp/src/Log/Engine/FileLog.php on line 133

パーミッションの設定がDockerに不足している?

CakePHP Error Warning: file_put_contents(/var/www/html/logs/error.log) #PHP - Qiita」にあるように、

docker exec -ti php_jaccs_auto bashでchmod a+w ./logs/*相当を実行すると解決した。ただし、事前にWindowsのExplorerで書き込みを許可しておく必要がある。git bashのchmodはWindowsには機能しない。

Warning: Warning (512): SplFileInfo::openFile(/var/www/html/tmp/cache/persistent/myapp_cake_core_translations_cake_en__u_s) [<a href='http://php.net/splfileinfo.openfile'>splfileinfo.openfile</a>]: failed to open stream: Permission denied in [/var/www/html/vendor/cakephp/cakephp/src/Cache/Engine/FileEngine.php, line 398]

Ref: CakePHP3でWarning Error: SplFileInfo::openFile()エラーが発生した場合の対処方法 | エス技研.

app.phpにmask=>0666を追加する。既存のキャッシュファイルは削除しておく。

dockerのアクセス権www-dataの問題の気がする。