[CakePHP3.6] Deprecated Error: You no longer need to call `Plugin::routes()` after upgrading to use Http\Server.メッセージ

bakeコマンドを使っていたら以下のメッセージが出力された。

Deprecated Error: You no longer need to call `Plugin::routes()` after upgrading to use Http\Server.
See https://book.cakephp.org/3.0/en/development/application.html#adding-the-new-http-stack-to-an-existing-application for upgrade information.
– cake_project\config\routes.php, line: 85
You can disable deprecation warnings by setting `Error.errorLevel` to `E_ALL & ~E_USER_DEPRECATED` in your config/app.php.
in [cake_project\vendor\cakephp\cakephp\src\Core\functions.php, line 310]

原因はroutes.php内でPlugin::routes();を呼び出しているため。
CakePHPのバージョンアップによって呼び出す必要がなくなったようなのでコメントアウトするとメッセージは出力されなくなった。

routes.php
Plugin::routes(); → //Plugin::routes();

CakePHP3とPHPUnitでControllerの単体テストを実施してみた

CakePHP3とPHPUnitでの単体テストコードの勉強をするために簡単なコードを書いて実施してみた。

環境
CakePHP 3.6.3
PHPUnit 5.7.27
PHP 7.0.27

UsersController.phpにsum()を追加する。
sum()はGETまたはPOSTから渡されるパラメータa、bの値を足し算する。

//UsersController.php
public function sum()
{
    $this->request->allowMethod(['post', 'get']);
    if($this->request->is('post')) {
        $a = $this->request->getData('a');
        $b = $this->request->getData('b');
    } elseif ($this->request->is('get')) {
        $a = $this->request->getQuery('a');
        $b = $this->request->getQuery('b');
    }
    $this->set('sum', $a + $b);
}

Controllerがsum()なのでsum.ctpテンプレートを追加する。

//Template/Users/sum.ctp
<?php
echo $sum;

UsersControllerTest.phpにはGETとPOST用のコードを作成する。
viewVariable()はControllerからset()した値を取得している。

//UsersControllerTest.php
public function testSumGet()
{
    $this->get('Users/sum?a=0&b=0');
    $sum = $this->viewVariable('sum');
    $this->assertEquals(0, $sum);

    $this->get('Users/sum?a=10&b=20');
    $sum = $this->viewVariable('sum');
    $this->assertEquals(30, $sum);

    $this->get('Users/sum?a=1000000&b=2000000');
    $sum = $this->viewVariable('sum');
    $this->assertEquals(3000000, $sum);
}

public function testSumPost()
{
    $this->post('Users/sum', ['a' => 0, 'b' => 0]);
    $sum =  $this->viewVariable('sum');
    $this->assertEquals(0, $sum);

    $this->post('Users/sum', ['a' => 10, 'b' => 20]);
    $sum =  $this->viewVariable('sum');
    $this->assertEquals(30, $sum);

    $this->post('Users/sum', ['a' => 1000000, 'b' => 2000000]);
    $sum =  $this->viewVariable('sum');
    $this->assertEquals(3000000, $sum);
}

PHPUnitを実行すると以下のような成功メッセージが出力される。

> php vendor\phpunit\phpunit\phpunit --coverage-html ./report.html tests\TestCase\Controller\UsersControllerTest.php

PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)

Time: 1.91 seconds, Memory: 12.00MB

OK (2 tests, 6 assertions)

Generating code coverage report in HTML format ... done

・途中で手が止まった点
testSumGet()とtestSumPost()の2つ目以降のテストがエラーになっていた。
メッセージを見るとControllerから受け取る$sumがnullになっていた。
原因はTemplate/Users/sum.ctpを作成していなかったため。
cli-error.logにテンプレートファイルが見つからないエラーが出ていた。

・今回解決できなかった点
UsersController.phpのsum()はGETとPOST以外は許容していない。
allowMethod()で指定したメソッド以外のアクセスは
500エラーが返るのでassertResponseFailure()を使ったテストコードを作った。
その結果、テストコードは成功した。
しかし、カバレッジレポートが生成されるがテストが通過したことにならなかった。

CakePHP3でPHPUnitのテストをしようとしていたときに出たエラーメッセージ

CakePHP3でPHPUnitのテストをしようとしていたときに出たエラーメッセージ。

・テスト用のデータベースが見つからなかっときのエラーメッセージ
Exception: Unable to insert fixtures for “test class path” test case.
SQLSTATE[HY000] [1049] Unknown database ‘database name’ in [cake php class file path]

原因
‘database name’データベースが存在しないとき

対処
app.phpファイルの’Datasources’ => ‘test’ => ‘database’にテスト用のデータベースを指定する。

・テスト用のデータベースのusernameかpasswordが間違っているときのエラーメッセージ
Exception: Unable to insert fixtures for “test class path” test case.
SQLSTATE[HY000] [1045] Access denied for user ‘user name’@’localhost’ (using password: YES) in [cake php class file path]

原因
ユーザ名かパスワード誤り

対処
app.phpファイルの’Datasources’ => ‘test’ => ‘username’、または’password’にテスト用のデータベースのユーザ名、パスワードを指定する。

CakePHP3とPHPUnitを使って単体を実施したらClass could not be foundメッセージが表示された

CakePHP3のドキュメントを元にPHPUnitを使って単体を実施したら以下のメッセージが表示された。
Class ‘tests\TestCase\View\Helper\ProgressHelperTest’ could not be found in ‘tests\TestCase\View\Helper\ProgressHelperTest.php’.

原因
ドキュメントを参考にして書いていたので「<?php」を付け忘れていた。

付けたあとに実行すると正常にPHPUnitが終了した。

vendor\bin\phpunit tests\TestCase\View\Helper\ProgressHelperTest
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 256 ms, Memory: 6.00MB

OK (1 test, 3 assertions)

バージョン
CakePHP 3.x
PHPUnit 5.7.27

CakePHP3でColumn not found: 1054 Unknown columnエラーが発生した原因と対処

背景
CakePHP3でTableクラスで期待しているカラム名とMySQLのカラム名に差異があった。
そこでMySQL側のカラム名の修正をした。
しかし、Column not found: 1054 Unknown columnエラーが発生した。

原因
Tableクラスで期待しているカラム名とMySQLのカラム名は合わせていた。
しかし、cake_project/tmp/cache/modelsディレクトリ以下にあるmyapp_cake_model_default_table_nameの中身を見ると古いカラム名のままだった。

対処内容
cake_project/tmp/cache/modelsディレクトリ以下にあるmyapp_cake_model_default_table_nameのファイルを削除した。

※上記のパスの「cake_project」はCakePHP3プロジェクトのルートディレクトリ、「table_name」はMySQLのテーブル名。

CodeanywhereでMySQLにアクセスする方法

CodeanywhereでMySQLにアクセスする方法は(私が知っているもので)2つある。

・ブラウザでCodeanywhereのSSH Terminalからアクセスする
Codeanywhereの左メニューからConnectionの上(画像ではcakeがConnection名)で右クリックしてSSH Terminalを選択する。
SSH Terminal上で「mysql -u root」コマンドを実行することでMySQLにアクセスができる。

2018-04-04_Codeanywhere-002

・phpMyAdminからアクセスする
Codeanywhereの左メニューからConnectionの上で右クリックしてInfoを選択する。
Connectionに付けた名前のタブが開き、「To access phpMyAdmin on your Container use the following link:」にphpMyAdminのURLが書いてあるのでコピーをする。
ブラウザからURLにアクセスをするとphpMyAdminにアクセスできる。
ユーザ名はroot、パスワードは空でMySQLにアクセスができる。

2018-04-04_Codeanywhere-003

CodeanywhereでSSH Terminalがみつからなくて時間をとられた

CodeanywhereでSSH Terminalがみつからなかった。
ドキュメントも読んだけれどわからずYou Tubeの動画を見ていたらわかった。

ドキュメントではコネクションの上で右クリックしてSSH terminalが選べると書いてある。

Simply right click on your connection with SSH access and select SSH terminal.

Conectionsを右クリックしてもSSH Terminalは出てこない。

2018-04-04_Codeanywhere-001

Connectionsの下のConnection(画像の場合はcake)を右クリックすると出てきた。
恥ずかしながらこれを解決するのにその日には終わらなかった。

2018-04-04_Codeanywhere-002

CakePHP3で1Controller、1Templateのページを作る

CakePHP3で1Controller、1Templateのページを作る。
題材は画面から身長と体重を入力したらBMIを表示してくれるページ。入力チェックは実施しない。

環境
CakePHP 3.5.10

Controller
src\Controller\BmiController.php

<?php
namespace App\Controller;
use App\Controller\AppController;

class BmiController extends AppController
{
  public function index()
  {
  }

  public function calculate() {
    //$this->autoRender = false;
    $height = $this->request->getData('height') / 100;
    $weight = $this->request->getData('weight');
    $this->set('bmi', round($weight / ($height * $height), 1));
    $this->render('index');
  }
}

Template
src\Template\Bmi\index.ctp

<?php
$this->layout = false;
?>
<!doctype html>
<html lang="ja">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    <title>bmi calculator</title>
  </head>
  <body>
    <div class="mx-auto" style="width: 400px;">
    <h1>bmi calculator</h1>
    <?php
    echo $this->Form->create('', ['url' => ['action' => 'calculate']]); 
    echo $this->Form->Control('身長(cm)', ['name' => 'height', 'required']);
    echo $this->Form->Control('体重(Kg)', ['name' => 'weight', 'required']);
    echo $this->Form->button('計算する', ['class' => 'btn btn-primary', 'type' => 'submit']);
    echo $this->Form->button('リセット', ['class' => 'btn', 'type' => 'reset']);
    echo $this->Form->end();
    ?>
    <?php if (!empty($bmi)): ?>
      あなたのBMIは<?= $bmi ?>です。
    <?php endif; ?>
    </div>
  </body>
</html>

ControllerとTemplateの作成が終わったらhttp://localhost:8765/bmiにアクセスすると以下のようなページが出力できる。

bmi-calculator
作成したページの画面

CakePHP3でデフォルトのレイアウトを無効にする方法

CakePHP3を始めてからctpファイルを用いて画面を表示させると緑色したヘッダー部分も一緒に表示される。
ちなみにこのヘッダー部分の記述はsrc\Template\Layout\default.ctpに書かれている内容。

このヘッダー部分を表示させたくないときにはctpファイルに以下の記述を追加してやればよい。

<?php
$this->layout = false;
?>

環境
CakePHP 3.5.10