Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

テーブル

Articlesテーブルの$idでCategories、Avatars、ReadMarksの情報を含めて返却して欲しいときは以下の用に書く。

        $article = $this->Articles->get($id,[
            'contain' => ['Categories', 'Avatars', 'ReadMarks']
        ]);

同一のアバターIDでArticleIDが指定のものより一つ大きいものを取ってくる。

        $result = $this->find('all', [
            'conditions' => ["avatar_id" => $avatarId,
            "id >" => $articleId,
            ], 
            'limit' => 1
        ]);

        if (empty($result)) {
            return null;
        } else {
            $list = $result->toArray();
            if (count($list) == 0) {
                return null;
            } else {
                return $list[0];
            }
        }

limitを使うべきなのかも。

データベースに接続、テーブル作成

use hoge;

で接続。テーブル一覧は

show tables;

で見れる。テーブル作成例。

create table 'hoge_messages' (`id` int(10) auto_increment not null comment 'id', `user_id` int(10) not null comment 'ユーザID', `name` varchar(255) default NULL comment 'チャットネーム', `body` varchar(255) default NULL comment 'チャット本文', `created` datetime comment 'created', `modified` datetime comment 'modified', constraint `chat_messages_PKC` primary key (`id`)) comment 'チャット' ;

パスワード変更

phpmyadminから入ってmysqlのパスワードを変更したところアクセスできなくなった。

パスワードの再設定 mysqlのパスワード変更はmysqlから

 SET PASSWORD = PASSWORD('hoge');

で変更できる。

対応してphpMyAdminの設定ファイルを書き換える必要がある。

/Applications/MAMP/bin/phpMyAdmin/config.inc.php

認証 AuthComponent

認証 - 3.x

AuthComponentは三タイプの認証できる。

  1. FormAuthenticate ログインフォーム POSTで (デフォルト)
  2. BasicAuthenticate ベーシック認証
  3. DigestAuthenticate ダイジェストHTTP認証

認証ハンドラの設定

// シンプルな設定
public function initialize()
{
    parent::initialize();
    $this->loadComponent('Auth', [
        'authenticate' => [
            'Form' => [
                'fields' => ['username' => 'email', 'password' => 'passwd']
            ]
        ]
    ]);
}
>|php|
// 'all' を使って設定を記述
$this->Auth->config('authenticate', [
    AuthComponent::ALL => ['userModel' => 'Members'],
    'Basic',
    'Form'
]);

userModelはデフォルトはUsersとなっているのでそうであれば設定不要。

ログインのサンプル

public function login()
{
    if ($this->request->is('post')) {
        $user = $this->Auth->identify();
        if ($user) {
            $this->Auth->setUser($user);
            return $this->redirect($this->Auth->redirectUrl());
        } else {
            $this->Flash->error(__('Username or password is incorrect'));
        }
    }
}

unauthenticated()は認証されていないユーザがアクセスした際に呼ばれる。

認証関連のフラッシュメッセージの表示

src/Template/Layout/default.ctp の body 部でecho $this->Flash->render();を加える。

ハッシュ化

DefaultPasswordHasher

namespace App\Model\Entity;

use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;

class User extends Entity
{

    // ...

    protected function _setPassword($password)
    {
        if (strlen($password) > 0) {
          return (new DefaultPasswordHasher)->hash($password);
        }
    }

    // ...
}

現在のログインID

$this->Auth->user('id');
で取得できる。

ログアウト

AuthComponent::logout()

public function logout()
{
    return $this->redirect($this->Auth->logout());
}

ユーザ毎のリソース認可

ControllerAuthorize

公開するところ
AuthComponent::allow($actions = null)
公開アクションを拒否
AuthComponent::deny($actions = null)

コントローラのコールバックで

ControllerAuthorize

ビヘイビア群

CounterCacheBehavior

例えばコメント数をエンティティが保存、削除されるたびに更新される。
belongsTo アソシエーションにしか効かない。

class CommentsTable extends Table
{
    public function initialize(array $config)
    {
        $this->addBehavior('CounterCache', [
            'Articles' => ['comment_count']
        ]);
    }
}

細かいカスタマイズは以下
CounterCache - 3.x

TimestampBehavior

created や modified を更新してくれる。
Timestamp - 3.x

TranslateBehavior

翻訳

TreeBehavior

ツリー構造
テーブルがnullableなparent_idを持ち、整数、符号付きなlftとrghtを持つこと。

以下はまだ実感が無いので保留。
Tree - 3.x

使い方

class CategoriesTable extends Table
{
    public function initialize(array $config)
    {
        $this->addBehavior('Tree');
    }
}
で読み込む。
再構築
>|php|
$categories = TableRegistry::get('Categories');
$categories->recover();
$node = $categories->get(1);
echo $categories->childCount($node);
$descendants = $categories->find('children', ['for' => 1]);

foreach ($descendants as $category) {
    echo $category->name . "\n";
}

ビヘイビア

ビヘイビアとはテーブルに追加できる便利部品
以下を参照した。
ビヘイビアー - 3.x

ビヘイビアをテーブルに追加

amespace App\Model\Table;

use Cake\ORM\Table;

class HogesTable extends Table
{
    public function initialize(array $config)
    {
        $this->addBehavior('Timestamp');
    }
}

追加設定

namespace App\Model\Table;

use Cake\ORM\Table;

class HogesTable extends Table
{
    public function initialize(array $config)
    {
        $this->addBehavior('Timestamp', [
            'events' => [
                'Model.beforeSave' => [
                    'created_at' => 'new',
                    'modified_at' => 'always'
                ]
            ]
        ]);
    }
}

removeBehaviorで削除。

既存のビヘイビア

  1. CounterCache
  2. Timestamp
  3. Translate
  4. Tree

ビヘイビアの作成

namespace App\Model\Behavior;

use Cake\ORM\Behavior;

class HogeBehavior extends Behavior
{
 public function initialize(array $config)
 {
    // 何らかの初期化処理
 }
}

ビヘイビアを追加するとビヘイビアーのパブリックメソッドが、追加されたテーブルオブジェクトに「ミックスイン」メソッドとして追加される。

  1. 複数追加したビヘイビアが同じメソッドを持つと例外発生。
  2. テーブルが同じメソッドを持つとそちらが呼ばれる。

公開したくないビヘイビアのpublicメソッドがあればimplementMethods設定で隠せる。

ビヘイビアでコールバックを実装すればミックスインされるのでイベントを処理できる。

    public function beforeSave(Event $event, EntityInterface $entity)
    {
        $this->slug($entity);
    }

読み込まれたビヘイビアの確認

$table->behaviors()->loaded();
$table->behaviors()->has('CounterCache');
$table->behaviors()->get('CounterCache');

ロードされたビヘイビアの再構成

BehaviorRegistry::getとconfigでできるらしい。

コンポーネント

コントローラで使える部品。
以下を参照した。

設定が必要なコンポーネントを使う際の設定

class HogesController extends AppController
{
    public function initialize()
    {
        parent::initialize();

        $this->loadComponent('Auth', [
            'authorize' => 'Controller',
            'loginAction' => ['controller' => 'Users', 'action' => 'login']
        ]);

        $this->loadComponent('Cookie', ['expires' => '1 day']);
    }

}

Controller->beforeFilter()でconfig()を使って設定する方法もあり。
設定は$this->Auth->config('loginAction');でよみ取れる。

コンポーネントの使用

        if ($this->Post->delete($this->request->getData('Post.id')) {

要するに移譲している。

コンポーネントの実装

namespace App\Controller\Component;

use Cake\Controller\Component;

class MathComponent extends Component
{
    public function doComplexOperation($amount1, $amount2)
    {
        return $amount1 + $amount2;
    }
}

コンポーネントから他のコンポーネントを使う。

   public $components = ['Existing'];

これで$this->Existingとなってコンポーネントから色々使える。

コンポーネントからコントローラにアクセス。。orz
$controller = $this->_registry->getController();
$controller = $event->getSubject();
コールバック
  1. beforeFilter(Event $event)
  2. startup(Event $event)
  3. beforeRender(Event $event)
  4. shutdown(Event $event)
  5. beforeRedirect(Event $event, $url, Response $response)