さくら VPS -> CakePHP3

Posted by muchag | CakePHP 3.x,CentOS,さくらインターネット | 2018-01-18 (木) 19:37:55

【環境】
CakePHP: 3.5.8
php: 7.1.13
CentOS: 7.4.1708
さくらインターネット:VPS 2G プラン
ディレクトリ作成

後述するけど、Composer は root では使わない方がよいそうなので
一般ユーザで操作。

そのため、先にroot でディレクトリを作成して
パーミッションを設定しておく必要がある。


mkdir /var/www/my_app
cd /var/www
chown apache:[username] my_app
chmod 775 my_app
  1. ディレクトリ作成
  2. ディレクトリ移動
  3. 所有者変更
  4. パーミッションを設定
インストール

一般ユーザへ変更してから。


composer create-project --prefer-dist cakephp/app /var/www/my_app
試行錯誤
インストール警告

root でインストールをしようとすると、下記警告が出る。


composer create-project --prefer-dist cakephp/app /var/www/my_app
Do not run Composer as root/super user! See https://getcomposer.org/root for details
インストール例外

上記コマンドにてインストールをしようとしたところ
下記例外が投げられた。

[Composer\Downloader\TransportException]
The “https://packagist.org/p/provider-latest%240cbfb40ab72a881d21b70f78286d39cd72e3b0eb8704c13e79dc49624e549973.json” file could not be downloaded (HTTP/1.1 404 Not Found)
対応1

Google 先生に質問し、1つ目の対応。
下記参考サイトによると、composer の健康診断コマンドらしい。

参考サイトの内容とは異なるけど、まずは診断。


composer diag
Checking platform settings: OK
Checking git settings: OK
Checking http connectivity to packagist: OK
Checking https connectivity to packagist: OK
Checking github.com rate limit: OK
Checking disk free space: OK
Checking pubkeys:
Tags Public Key Fingerprint: 57815BA2 7E54DC31 7ECC7CC5 573090D0  87719BA6 8F3BB723 4E5D42D0 84A14642
Dev Public Key Fingerprint: 4AC45767 E5EC2265 2F0C1167 CBBB8A2B  0C708369 153E328C AD90147D AFE50952
OK
Checking composer version: OK
Composer version: 1.6.2
PHP version: 7.1.13
PHP binary path: /usr/bin/php

問題ないみたい。

参考サイト

ふたりはララベル:Composerのエラーの原因を調査する(2014-08-23)

対応2

下記参考サイトを見つけて、わけもわからないまま対応。


wget http://curl.haxx.se/ca/cacert.pem
cp -v -f cacert.pem /etc/pki/tls/certs/ca-bundle-curl.crt
  1. OpenSSL(正確にはcurl)で使用するCAをダウンロード
  2. 当該ファイルを、本家(?)ca-bundle.crt の存在するディレクトリへコピー

注意事項

このcrtファイルはcurlのエラーを回避するためのものですので、本来のca-bundle.crtを上書きしないように注意して下さい。

Qiita:ComposerからLaravelを導入しようとしてOpenSSL周りのエラーで困った件(2015-06-23)

php.ini へ上記ファイルを設定


vim /etc/php.ini

curl.cainfo=/etc/pki/tls/certs/ca-bundle-curl.crt
openssl.cafile=/etc/pki/tls/certs/ca-bundle-curl.crt
ファイルパス

最初コピペで作業をして、下記のように怒られた。


cp -v -f cacert.pem /full/path/to/certs/ca-bundle-curl.crt
`cacert.pem' -> `/full/path/to/certs/ca-bundle-curl.crt'
cp: 通常ファイル `/full/path/to/certs/ca-bundle-curl.crt' を作成できません: そのようなファイルやディレクトリはありません

そりゃ、/full/path/to は見つからなくて怒られるよねw

でも、コピー先のディレクトリがわからなかったので、
注意書きに書かれていた ca-bundle.crt ファイルを検索。


find / -name 'ca-bundle.crt'
/etc/pki/tls/certs/ca-bundle.crt
参考サイト

Qiita:ComposerからLaravelを導入しようとしてOpenSSL周りのエラーで困った件(2015-06-23)

解決

上記「対応2」で解決!
ありがたや~。

CakePHP 3.x,CentOS,さくらインターネット | 2018-01-18 (木) 19:37:55 |

挿入

Posted by muchag | CakePHP 3.x | 2018-01-08 (月) 16:22:17


公式:データの保存

【環境】
CakePHP: 3.5.8
php: 7.1.5
基本

use Cake\ORM\TableRegistry;

$articlesTable = TableRegistry::get('MyVendor/MyPlugin.Articles');
$article = $articlesTable->newEntity();

$article->title = '新しい記事';
$article->body = 'これは記事の本文です';

if ($articlesTable->save($article)) {
    // $article エンティティーは今や id を持っています
    $id = $article->id;
}
バルクインサート

これすごい!!!
メッチャ楽~♪


$users = array(
	0 => array(
	  'name' => 'Santa',
	  'age' => 25,
	  'created' => '2017-12-24 20:52:00',
	  'modified' => '2017-12-24 20:52:00',
	),
	1 => array(
	  'name' => 'Claus',
	  'age' => 52,
	  'created' => '2017-12-24 20:52:00',
	  'modified' => '2017-12-24 20:52:00',
	),
);

$fields = [
	'name',
	'age',
	'created',
	'modified',
];

$table = TableRegistry::get('Users');

$query = $table->query()
	->insert($fields);

$values_expression = $query->clause('values')->values($data);

$query = $query
	->values($values_expression)
	->execute();

ただし、28行目は、注意。

ただしclause()はqueryを返すものじゃないので、続けて書けないのでそこは注意
なので、最初の例のように一旦切ってくださいな

杏z 学習帳:[CakePHP]QueryBuilderを使ってバルクインサート(2016-03-16)

だそうなので、その通りにしたけど
->insert() より前にしたら、エラーになった。

つまり、->insert() で設定したカラムに対して
値をまとめてセットして、クエリを実行する
という流れなのね~。

ON DUPLICATE KEY UPDATE

epilog メソッドを用いて、更新対象カラムを指定。


$query->epilog('ON DUPLICATE KEY UPDATE `name`=VALUES(`name`), `modified`=VALUES(`modified`)');
参考サイト

杏z 学習帳:[CakePHP]QueryBuilderを使ってバルクインサート(2016-03-16)

Advanceffort WEB戦略会議室!:CakePHP3 クエリ作成パターンまとめ(find)(2016-02-14)

Qiita:CakePHP 3のQueryBuilderの使い方をまとめてみた!(2014-12-12)

CakePHP 3.x | 2018-01-08 (月) 16:22:17 |

debug

Posted by muchag | CakePHP 3.x | 2018-01-08 (月) 15:18:08

クエリのデバッグを行うメソッド。

公式:データの取り出しと結果セット クエリーのデバッグと結果セット

【環境】
CakePHP: 3.5.8
php: 7.1.5
種類
  • debug($query) SQL とバインドパラメーターが表示されます。結果は表示されません。
  • debug($query->all()) ResultSet のプロパティー (結果ではなく) が表示されます。
  • debug($query->toArray()) 結果を個々に見る簡単な方法です。
  • debug(json_encode($query, JSON_PRETTY_PRINT)) 人に読みやすい形で結果を表示します。
  • debug($query->first()) 単一のエンティティーのプロパティーを表示します。
  • debug((string)$query->first()) 単一のエンティティーのプロパティーを JSON として表示します。
CakePHP 3.x | 2018-01-08 (月) 15:18:08 |

finder

Posted by muchag | CakePHP 3.x | 2018-01-08 (月) 15:17:49

結果セット取得便利メソッド。

公式:データの取り出しと結果セット データのロードに Finder を使う

【環境】
CakePHP: 3.5.8
php: 7.1.5
書式
/vendor/cakephp/cakephp/src/ORM/Table.php

public function find($type = 'all', $options = [])

第1引数:ファイダタイプ。デフォルトは all
第2引数:オプション

タイプ

ファインダタイプを指定することで、専用ファインダメソッドを呼び出せる。

デフォルト
/vendor/cakephp/cakephp/src/ORM/Table.php

public function findAll(Query $query, array $options)

public function findList(Query $query, array $options)

public function findThreaded(Query $query, array $options)

とあるので
タイプには、上記3種は指定可能だと思う。

連鎖

find メソッドを繋げることも可能。


$children = $categories
    ->find('children', ['for' => 1])
    ->find('threaded')
    ->toArray();

公式:Tree クイックツアー
こちらに記載されている上記コードを実行してみて
ちゃんと目的通りの結果を得られたので
こういう記述が可能であることは理解できた。

が、どういう仕組みになっているのかは、現在不明。

オプション
  • conditions クエリーの WHERE 句に使う条件を提供します。
  • limit 欲しい行数をセットします。
  • offset 欲しいページオフセットをセットします。 page をあわせて使うことで計算を簡単にできます。
  • contain 関連をイーガーロード (eager load) するように定義します。
  • fields エンティティーへとロードされる列を制限します。いくつかの列だけがロードされることになるので エンティティーが正しく動かないこともありえます。
  • group クエリーに GROUP BY 句を加えます。集約関数を使う際に便利です。
  • having クエリーに HAVING 句を加えます。
  • join カスタム JOIN を追加で定義します。
  • order 結果セットに並び順を設定します。
カスタム(自作)

公式:データの取り出しと結果セット カスタム Finder メソッド

書式

use Cake\ORM\Query;
use Cake\ORM\Table;

class ArticlesTable extends Table
{

    public function findOwnedBy(Query $query, array $options)
    {
        $user = $options['user'];
        return $query->where(['author_id' => $user->id]);
    }

}

// コントローラーやテーブルのメソッド内で
$articles = TableRegistry::get('Articles');
$query = $articles->find('ownedBy', ['user' => $userEntity]);
動的

Symfony 2 のときと考え方は同じ~♪


// findBy, findAllBy の後ろにカラム名を付ける
// 引数に、当該カラムに設定したい検索条件を設定する
$query = $this->Users->findByUsername('joebob');

// 複数カラムの場合は、And, Or で繋げる
// 但し、And, Or の混在は NG
$query = $users->findAllByUsernameAndApproved('joebob', 1);
$query = $users->findAllByUsernameOrEmail('joebob', 'joe@example.com');

// カスタムファインダにも利用可能
$query = $users->findTrollsByUsername('bro');
CakePHP 3.x | 2018-01-08 (月) 15:17:49 |

get

Posted by muchag | CakePHP 3.x | 2018-01-08 (月) 15:16:19

主キーで単一のエンティティーを取得するメソッド。

公式:データの取り出しと結果セット 主キーで単一のエンティティーを取得する

【環境】
CakePHP: 3.5.8
php: 7.1.5
書式
/vendor/cakephp/cakephp/src/ORM/Table.php

public function get($primaryKey, $options = [])

第1引数:プライマリキー値。一般的には id
第2引数:テーブル結合などのオプション

オプション

判明したら追記。


$article = $articles->get($id, [
    'cache' => 'custom',        // cache
    'contain' => ['Comments'],  // JOIN
    'finder' => 'translations', // finder
]);
CakePHP 3.x | 2018-01-08 (月) 15:16:19 |

データ取得

Posted by muchag | CakePHP 3.x | 2017-12-23 (土) 0:40:15


公式:データベースアクセス & ORM
公式:クエリービルダー
公式:データの取り出しと結果セット
公式:データの保存

【環境】
CakePHP: 3.5.8
php: 7.1.5
取得タイプ

// 全行取得
$results = $articles->find()->all();

// 全行を配列に変換して取得
$results = $articles->find()->toArray();

// 先頭の1行だけ取得
$results = $articles->find()->first();
SELECT
フィールド指定

テーブル名を省略すると、
自動的に当該テーブル(FROM に設定されるテーブル)のカラムとして認識される。


$query = $articles->find();
$query->select(['country']);

$query = $articles->find();
$query->select(['Users.country']);

SELECT DISTINCT Users.country AS `Users__country`

よって、普段からテーブル名を付記する癖を付ける方がよさそう。

DISTINCT

$query = $articles->find();
$query->select(['Users.country'])
      ->distinct(['Users.country']);

SELECT DISTINCT Users.country AS `Users__country`
COUNT

$query = $articles->find();
$query->select(['count' => $query->func()->count('*')]);

SELECT COUNT(*) AS count
GROUP BY

$query = $articles->find();
$query = ->group(['Users.country', 'Users.gender']);

GROUP BY
    Users.country,
    Users.gender
WITH ROLLUP

GROUP BY -> WITH ROLLUP


$query = $articles->find();
$query = ->group(['Users.country', 'Users.gender'])
         ->epilog('WITH ROLLUP');

Raph’s world:CakePHP 3 ORM – with rollup(2015-09-20)
こちらには、上記のようにするように書いてあったけど
これではエラーになる。

500エラーだけど、原因は探っていない。

その上に書いてあった、下記の書式で誤魔化せた。
GROUP BY -> WITH ROLLUP


$query = $articles->find();
$query = ->group(['Users.country', 'Users.gender WITH ROLLUP']);

GROUP BY
    Users.country,
    Users.gender WITH ROLLUP

但し!
抽出カラムと GROUP BY 指定カラムが同一でなければエラーになる。

Error: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘database_name.Users.id’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

CakePHP3 では、JOIN したテーブルの id カラムを自動的に抽出カラムに加えるので
最初から抽出カラムに指定した上で、GROUP BY 対象にも指定する必要がある。

ORDER BY

$query = $articles->find();
$query = ->order(['Users.country' => 'ASC', 'Users.gender' => 'DESC']);

ORDER BY
    Users.country ASC
    Users.gender DESC
CakePHP 3.x | 2017-12-23 (土) 0:40:15 |

初期設定

Posted by muchag | CakePHP 3.x | 2017-12-10 (日) 23:20:05

【環境】
CakePHP: 3.5.6
php: 7.1.5
app.php
/config/app.php
ローカライズ

App 項目の defaultLocale を ja_JP とする。


'App' => [
    'namespace' => 'App',
    'encoding' => env('APP_ENCODING', 'UTF-8'),
    'defaultLocale' => env('APP_DEFAULT_LOCALE', 'en_US'),
    'base' => false,
    'dir' => 'src',
    'webroot' => 'webroot',
    'wwwRoot' => WWW_ROOT,
    // 'baseUrl' => env('SCRIPT_NAME'),
    'fullBaseUrl' => false,
    'imageBaseUrl' => 'img/',
    'cssBaseUrl' => 'css/',
    'jsBaseUrl' => 'js/',
    'paths' => [
        'plugins' => [ROOT . DS . 'plugins' . DS],
        'templates' => [APP . 'Template' . DS],
        'locales' => [APP . 'Locale' . DS],
    ],
],
DB

DB 周りの設定。

  • host
  • usernama:MySQL のユーザ名
  • password:MySQL パスワード
  • database:当該アプリデータベース名(テスト用は、test_ プレフィクスを付ける)
  • timezone:Asia/Tokyo

'Datasources' => [
    'default' => [
        'className' => 'Cake\Database\Connection',
        'driver' => 'Cake\Database\Driver\Mysql',
        'persistent' => false,
        'host' => 'localhost',
        /**
         * CakePHP will use the default DB port based on the driver selected
         * MySQL on MAMP uses port 8889, MAMP users will want to uncomment
         * the following line and set the port accordingly
         */
        //'port' => 'non_standard_port_number',
        'username' => 'my_app',
        'password' => 'secret',
        'database' => 'test_myapp',
        'encoding' => 'utf8',
        'timezone' => 'UTC',

    'test' => [
        'className' => 'Cake\Database\Connection',
        'driver' => 'Cake\Database\Driver\Mysql',
        'persistent' => false,
        'host' => 'localhost',
        //'port' => 'non_standard_port_number',
        'username' => 'my_app',
        'password' => 'secret',
        'database' => 'test_myapp',
        'encoding' => 'utf8',
        'timezone' => 'UTC',
タイムゾーンエラー

タイムゾーンに Asia/Tokyo を設定したら
苦労して辿り着いた CakePHP3 のTOPページが姿を消し
エラーの画面になった。 X-P

SQLSTATE[HY000]: General error: 1298 Unknown or incorrect time zone: ‘Asia/Tokyo’

そして、MySQL への対応。
タイムゾーン

bootstrap.php
タイムゾーン

- date_default_timezone_set('UTC');
+ date_default_timezone_set('Asia/Tokyo');
.htaccess

アプリケーションディレクトリに phpMyAdmin を配置するとき
こちらも CakePHP のルーティング対象となってしまうため
ルーティングルールから除外する必要が生じる。


<IfModule mod_rewrite.c>
    RewriteEngine on    
+   RewriteCond   %{REQUEST_URI} !(^/pma/)
    RewriteRule   ^$    webroot/    [L]
+   RewriteCond   %{REQUEST_URI} !(^/pma/)
    RewriteRule   (.*) webroot/$1    [L]
</IfModule>

除外ルールは、各リライトルールに対して設定する必要があるため
同じ内容を2回記述する必要がある。

参考サイト

Step On Board:RewriteCondが効かない?特定のディレクトリを除外する方法でつまずいたお話(2015-05-13)

CakePHP 3.x | 2017-12-10 (日) 23:20:05 |

バージョン情報

Posted by muchag | CakePHP 3.x | 2017-12-10 (日) 22:21:40

【環境】
CakePHP: 3.5.6
バージョン情報
/vendor/cakephp/cakephp/VERSION.txt

////////////////////////////////////////////////////////////////////////////////////////////////////
// +--------------------------------------------------------------------------------------------+ //
// CakePHP Version
//
// Holds a static string representing the current version of CakePHP
//
// CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
// Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
//
// Licensed under The MIT License
// Redistributions of files must retain the above copyright notice.
//
// @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
// @link          https://cakephp.org
// @since         CakePHP(tm) v 0.2.9
// @license       https://opensource.org/licenses/mit-license.php MIT License
// +--------------------------------------------------------------------------------------------+ //
////////////////////////////////////////////////////////////////////////////////////////////////////
3.5.6

派手な枠に目を取られて
最終行に書いてあることに気がつくのに
1分位かかったw

CakePHP 3.x | 2017-12-10 (日) 22:21:40 |

VirtualBox + CakePHP + Eclipse + xdebug

Posted by muchag | CakePHP 3.x,Eclipse,Library & PlugIn & AddIn,VirtualBox | 2017-12-09 (土) 21:31:49

【環境】
VirtualBox グラフィカルユーザーインターフェース: 5.1.24 r117012 (Qt5.6.2)
php: 7.1.5
CakePHP:3.4
Eclipse: 4.7
xdebug: 2.5.5
xdebug のインストール

yum --enablerepo=remi-php71 -y install php71-php-pecl-xdebug

例によって、標準以外のディレクリにインストールされるので、コピー。


find / -name 'xdebug.so'
/opt/remi/php71/root/usr/lib64/php/modules/xdebug.so
cp /opt/remi/php71/root/usr/lib64/php/modules/xdebug.so /usr/lib64/php/modules/xdebug.so
ll /usr/lib64/php/modules/ | grep xdebug
-rwxr-xr-x 1 root root  261560 12月  9 21:28 xdebug.so
設定
php.ini
/etc/php.ini

[xdebug]
zend_extension=xdebug.so
xdebug.default_enable = 1
xdebug.remote_enable = 1
xdebug.remote_port=9000
xdebug.remote_autostart=1
xdebug.remote_host=192.168.56.1
Eclipse
実行構成
  1. [実行]-[実行構成]
  2. 「実行構成」ダイアログ
    1. 左ペイン
      1. [PHP Web アプリケーション] を選択
      2. 上部ツールボタンから [新規の起動構成]
    2. 右ペイン
      1. 名前:任意
      2. 「サーバー」タブ
        1. PHP サーバー:[新規]
        2. 「PHP サーバーの作成」ダイアログ
          1. 「新規 PHP サーバー」
            1. サーバー名:任意
            2. ベース URL:http://192.168.56.2
            3. [次へ]
          2. 「デバッガー設定」
            1. デバッガー:[XDebug]
            2. 右の [グローバル設定] リンクをクリック
            3. 「XDebug」ダイアログ
              1. リモート・セッション受信(JIT):[任意] を選択
              2. [OK]
            4. ポート:任意(php.ini で設定した値)
            5. [次へ]
          3. 「パス・マッピング」
            1. [追加]
            2. 「パスマッピングの追加」ダイアログ
            3. 「新規パス・マッピングの追加」
              1. サーバー上のパス:/var/www/html/hoge
              2. 「ファイル・システムのパス」を選択
              3. ファイル・システムのパス:[参照] から、Windows ローカルの index.php があるディレクトリを選択
              4. [OK]
          4. [完了]
        3. ファイル:[参照] から、Eclipse プロジェクトディレクトリ内の index.php を選択
        4. URL
          1. [自動生成] の✔を外す
          2. URL:右のテキストボックスに /index.php
    3. [実行]
デバッグ

[ウインドウ]-[設定]
「設定」ダイアログ
左ペイン [PHP]-[デバッグ]
右ペイン [最初の行でブレーク] の✔を外す

デバッグ実行

[デバッグ] ツールボタン(虫アイコン)で、直前のデバッグ構成を実行。
[デバッグ] ツールボタン(虫アイコン)右の▼から、デバッグ対象を選択して実行。

リモート・セッション

実は上記設定を最初に行ったときは、
左記のようなアラートが出た。

アラートの [here] からダイアログを開き
リモート・セッション受信(JIT):[任意] を選択したら、
無事にブレークポイントで止まってくれた♪

外部ブラウザ

スマートフォンサイトのエミュレーションであったり
デベロッパーツールを利用するために
Chrome 上でデバッグを行いたい場合は
スマートフォンサイト

CakePHP 3.x,Eclipse,Library & PlugIn & AddIn,VirtualBox | 2017-12-09 (土) 21:31:49 |