RitoLabo

CakePHP3のコンポーネントとは?導入から共通処理をまとめる入門編

  • 公開:
  • 更新:
  • カテゴリ: PHP CakePHP
  • タグ: PHP,CakePHP,3.5,Component

今回は、CakePHP3のコンポーネントクラスを導入して共通処理をまとめるまでの基礎部分を行います。

アジェンダ
  1. 開発環境
  2. コンポーネント
  3. コンポーネント生成
  4. コンポーネント実装
  5. コンポーネントの読み込み・使用
  6. コントローラへのアクセス
  7. コンポーネント内で他のコンポーネントを使う
  8. コンポーネント継承による独自処理への置き換え・追加

開発環境

今回の開発環境は以下の通りです。

  • Linux CentOS 7
  • Apache 2.4
  • PHP 7.2
  • CakePHP 3.5

CakePHPのルートディレクトリを「cakephp/」とします。

コンポーネント

コンポーネントとは、広義には部品や要素など、ある何かを形作るための1部の事を指します。

そしてCakePHP3でもまさしく、コントローラ上で使う共通処理を「コンポーネント」という形でまとめる事が出来ます。

小さな処理を部品化(=コンポーネント化)する事で、それらを使い回し、効率の良い開発が行える。という事になります。この場合では、共通化とも置き換えられます。

公式CookBookにも記載がある通り、そのメソッド、コピペしようと思ったらコンポーネントにまとめてね!という事です。開発チームみんなが幸せになれる。それがコンポーネントです。

という事で、作業に入っていきます。

コンポーネント生成

まずはコンポーネントファイルを生成します。CakePHPルートディレクトリへ移動し、以下のbakeコマンドを叩きます。

# CakePHPのルートディレクトリへ移動する
cd /path/to/cakephp

# bakeコマンドでコンポーネントファイルを生成する
bin/cake bake component Common

# 実行結果
[demo@localhost cakephp]# bin/cake bake component Common

Creating file /var/www/html/cakephp/src/Controller/Component/CommonComponent.php
Wrote `/var/www/html/cakephp/src/Controller/Component/CommonComponent.php`
Deleted `/var/www/html/cakephp/src/Controller/Component/empty`

Baking test case for App\Controller\Component\CommonComponent ...
Deleted `/var/www/html/cakephp/tests/TestCase/Controller/Component/empty`

Creating file /var/www/html/cakephp/tests/TestCase/Controller/Component/CommonComponentTest.php
Wrote `/var/www/html/cakephp/tests/TestCase/Controller/Component/CommonComponentTest.php`

cakephp/src/Controller/Component 配下に CommonComponent.php が生成されます。

cakephp
├─ src
│   ├─ Controller
│   │   ├─ Component
│   │   │   └─
CommonComponent.php

初期ソースはこんな感じです。

cakephp/src/Controller/Component/CommonComponent.php
<?php
namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;

/**
* Common component
*/
class CommonComponent extends Component
{

/**
* Default configuration.
*
* @var array
*/
protected $_defaultConfig = [];
}

コンポーネント実装

それでは生成したコンポーネントクラスに機能を実装します。今回は、渡ってきた引き数が10よりも大きいかで真偽を返す簡単なメソッドを記述しました。

cakephp/src/Controller/Component/CommonComponent.php
<?php
namespace App\Controller\Component;

use Cake\Controller\Component;

/**
* Common component
*/
class CommonApiComponent extends Component
{
protected $_defaultConfig = [];

/**
* 引数の値が10よりも大きい事を返却する
* @param $number
* @return bool
*/
public function abcd($number)
{
if($number > 10) {
return true;
} else {
return false;
}
}
}

こういった簡単なものから、Tableオブジェクトを使ったDB系のアクションなど、コンポーネントでは必要なものを読み込んで柔軟に記述していく事が出来ます。

コンポーネントの読み込み・使用

作成したコンポーネントを使用する際も手順は極めてシンプルです。例えば、SampleController に以下のように実装します。

<?php
namespace App\Controller;

use App\Controller\AppController;
use Cake\ORM\TableRegistry;

class SampleController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('Common'); // コンポーネントの読み込み
}

public function index()
{
$number = 12;
// $number が 10 より大きいかを確認する
$ret = $this->CommonApi->abcd($number);

printr($ret);
}
}

コンストラクタであるinitialize()でCommonコンポーネントを読み込んでいます。コンポーネントはまず読み込みを行う事で使用できるようになります。

ちなみにinitialize内でなくても、index()など通常のアクションの中からでも読み込む事が可能です。

そしてindex()アクションでは
$this->CommonApi->abcd();
の形でコンポーネントを使う事が出来ます。

基本的な流れは以上です。

コントローラへのアクセス

コンポーネントは通常コントローラからコールされて使われますが、その中でコンポーネントからコントローラへアクセスする事も出来ます。

以下はコンポーネントクラスでの記述です。

public function abcd()
{
// 現在のコントローラーに アクセス
$controller = $this->_registry->getController();

// メンバ変数を参照したり
$param = $controller->hoge;

// メソッドもコール出来る
$result = $controller->getMyTreasure();

}

_registry から getController() で現在のコントローラを呼ぶ事が出来ます。

そしてそこからメンバ変数を参照したり、メソッドを実行したりもできます。

コントローラからコンポーネントへ値やインスタンスを渡さなくて良かったりするので地味に便利です。

コンポーネント内で他のコンポーネントを使う

あるコンポーネントの中で、他のコンポーネントを呼び出して使いたい場合があります。その場合は、以下のように記述します。

<?php
namespace App\Controller\Component;

use Cake\Controller\Component;

class CommonComponent extends Component
{

// 他のコンポーネントを読み込む
public $components = ['OtherOne', 'OtherTwo', 'OtherThree'];

public function index()
{
// 読み込んだコンポーネントを使用する
$ret = $this->OtherOne->hoge();

}
}

メンバ変数 $components にて、配列の形でコンポーネントを指定すれば、そのまま利用可能になります。

コンポーネント継承による独自処理への置き換え・追加

コントローラ内で読み込んでいるコンポーネントに対して、狙った部分だけ置き換えたり付け加えたりも出来ます。

その場合は、追加もしくは置き換えようとしている独自処理をコンポーネントとして作成し、それらを適宜コントローラで切り替えていく事ができます。

例えば既存のHogeコンポーネントに対して、ある部分で処理を付け加えて使用したいとします。

まずは追加メソッドを実装したコンポーネントを作成します。cakephp/src/Controller/Component 配下に MyHogeComponent.php を作成し、以下のように実装します。

cakephp/src/Controller/Component/MyHogeComponent.php
<?php
namespace App\Controller\Component;

use Cake\Controller\Component\HogeComponent;

class MyHogeComponent extends HogeComponent
{
public function plusMethod()
{
// 処理
}
}

HogeComponentを継承し、適宜追加分のメソッドを記述したり、HogeComponent内の置き換えたい処理を記述したりします。

独自コンポーネントの作成が終わったら、コントローラへ次のように記述します。

cakephp/src/Controller/SamplesController.php
class SamplesController extends AppController
{
public function initialize()
{
$this->loadComponent('Hoge', [
'className' => 'MyHoge'
]);
}
}

loadComponent()する際に、オプションでclassNameプロパティを設定する事で、コンポーネントを置き換える事が出来ます。

上記例の場合は、Sampleコントローラに対してはHogeコンポーネントを継承し独自処理を追加したMyHogeコンポーネントを割り当てることができる。というわけです。

まとめ

作業は以上です。コンポーネントを併用する事で、重複メソッドが無くなり見通しも良くメンテナンスしやすいソースコードになるので、是非試してみてください。