Pages

2019年5月8日水曜日

PhpStorm 割引販売のご紹介


https://secure.samuraism.com/referral/8BAEF98D2EE87690D23BB03ED3A7F393

PhpStorm は300円しか割引ありませんが、無いよりは良いですしね。
サムライズムって会社は2018年8月くらい(?)からの日本正規代理店みたいです。

2019年3月26日火曜日

PHPソースからフロー図の自動作成 Visustin以外で

以前 Visustin というツールを利用してPHPのソースからフロー図を作成しようとしただけど、何かしっくり来ない。。

そして別のツールが無いかなと探していたらこんなブラウザアプリを発見した。

code2flow
https://code2flow.com/


無料プランもあるみたい。

早速トップページ画面右上の GET STARTED から試してみた。



自分は今、メインで CakePHP3 を利用しているので、サンプルソースに ブックマークチュートリアル を利用した。

ブックマークチュートリアル
https://book.cakephp.org/3.0/ja/tutorials-and-examples/bookmarks/intro.html

Gut Hub
https://github.com/cakephp/bookmarker-tutorial



早速ソースをコピペしてみるとこんな感じに。
ん~ さすがに見やすい! とはならないけど、コメントもオレンジで表示されてて便利だ。
ソースやフロー図のところをマウスオーバーすると対となる箇所にガイドが付いて解りやすい。

ソースレビューなどを行う時にこれは便利な気がする。

なかなかこまめに使う場面が自分には無いけども、良いものを見つけたかな。

2018年11月21日水曜日

[CakePHP3] 管理画面とそれ意外でCSRF用のCookieName(クッキー名)を変更したい

/src/Application.php のデフォルト指定をまず削除。
本当は設定を更新したかったが、方法が見つからず。。

$middlewareQueue->get(3) からできるかなと思ったけど無理だよね。。
てか名前も指定できるようになってたらいいのに。。
->add した瞬間にこれ実行してるのかな。。

まーとりあえず以下の方法で対応しました。

public function middleware($middlewareQueue)
{
    $middlewareQueue
        // Catch any exceptions in the lower layers,
        // and make an error page/response
        ->add(ErrorHandlerMiddleware::class)

        // Handle plugin/theme assets like CakePHP normally does.
        ->add(AssetMiddleware::class)

        // Add routing middleware.
        // Routes collection cache enabled by default, to disable route caching
        // pass null as cacheConfig, example: `new RoutingMiddleware($this)`
        // you might want to disable this cache in case your routing is extremely simple
        ->add(new RoutingMiddleware($this, '_cake_routes_'))

        // Add csrf middleware.
        ->add(new CsrfProtectionMiddleware([
            'cookieName' => 'csrf',
            'secure' => true,
            'httpOnly' => true,
        ]));

    return $middlewareQueue;
}

上記がデフォルトの内容となりますが、これから

// Add csrf middleware.
->add(new CsrfProtectionMiddleware([
    'cookieName' => 'csrf',
    'secure' => true,
    'httpOnly' => true,
]));

の部分を削除します。

public function middleware($middlewareQueue)
{
    $middlewareQueue
        // Catch any exceptions in the lower layers,
        // and make an error page/response
        ->add(ErrorHandlerMiddleware::class)

        // Handle plugin/theme assets like CakePHP normally does.
        ->add(AssetMiddleware::class)

        // Add routing middleware.
        // Routes collection cache enabled by default, to disable route caching
        // pass null as cacheConfig, example: `new RoutingMiddleware($this)`
        // you might want to disable this cache in case your routing is extremely simple
        ->add(new RoutingMiddleware($this, '_cake_routes_'));

    return $middlewareQueue;
}

するとこうなる。

/src/Application.php で分岐させても良いけど、Pluginのための分岐なので、
分岐はPlugin側でやる事に。
/plugins/Manage/config/bootstrap.php

ちなみに /plugins/Manage は管理画面用に作成したプラグイン。

plugins/Manage/config/bootstrap.php を更新。

以下の分岐を作成していたので、その中で

use Cake\Event\EventManager;
use Cake\Http\Middleware\CsrfProtectionMiddleware;

$cookieName = 'csrf';
if (!empty($_SERVER['REQUEST_URI']) && preg_match('/^\/manage*/', $_SERVER['REQUEST_URI'])) {
    $cookieName = 'mcsrf';
}

EventManager::instance()->on(
    'Server.buildMiddleware',
    function ($event, \Cake\Http\MiddlewareQueue $middlewareQueue) use ($cookieName) {
        $middlewareQueue->add(new CsrfProtectionMiddleware([
            'cookieName' => $cookieName,
            'secure' => true,
            'httpOnly' => true,
        ]));
    });

のように更新すればOK。

で、確認してたらどうも csrf、mcsrf の両方が登録されてしまう。

何故なんだろうとハマっていたら DebugBar のAjax?で呼んでいる様子。
なので、 DEBUG false にして確認したら無事 /manage 以下では mcsrf だけが利用されており、 /manage と それ以外 で別のクッキー値を参照するようになりましたとさ。

2018年11月20日火曜日

[CakePHP3] セッション(Session)のモデル(テーブル)を通常と特定ディレクトリで分ける方法

SessionのストレージをDatabaseとしている事として以下をメモしています。

管理画面(/manage/*) と その他(/manage/*以外) でセッションデータを保存するDBテーブルを分ける方法。

管理画面(/manage/*) はプラグイン(Plugin)機能を利用して作成。

config/bootstrap.php からプラグインを呼び出す。

Plugin::load('Manage', ['bootstrap' => true, 'routes' => true]);

この時に 'bootstrap' => true を忘れないように。

plugins/Manage/config/bootstrap.php ファイルを作成し、中身は

<?php
use Cake\Core\Configure;

if (!empty($_SERVER['REQUEST_URI']) && preg_match('/^\/manage*/', $_SERVER['REQUEST_URI'])) {
    Configure::write('Session.handler.model','ManageSessions');
    Configure::write('Session.cookiePath','/manage/');
}

DBテーブルは分けるので
デフォルトの sessions と manage_sessions を用意する事を想定する。

CREATE TABLE `sessions` (
  `id` char(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
  `created` datetime DEFAULT CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
  `modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
  `data` blob DEFAULT NULL, -- for PostgreSQL use bytea instead of blob
  `expires` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `manage_sessions` (
  `id` char(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
  `created` datetime DEFAULT CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
  `modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- optional, requires MySQL 5.6.5+
  `data` blob DEFAULT NULL, -- for PostgreSQL use bytea instead of blob
  `expires` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2018年11月7日水曜日

[CakePHP3] オリジナルのログイン認証を作成

ちょっとややこしい要件が発生した。

ログインIDが1つでユニークではなく、店舗コード+社員コード という感じで2つのカラムでユニークとなる内容でした。

DBテーブルはこんな感じとする。

table: users
columns: id, shop_id, code, password

table: shops
columns: id, shop_id, code

そして、リクエスト値はこんな感じとする。

code, shop_code, password


やりたいSQLとしては

SELECT *
FROM users
INNER JOIN shops ON users.shop_id = shops.id
WHERE users.code = :code AND shops.code = :shop_code;

で取得してからパスワードチェックするというイメージ。

$this->loadComponent('Auth', [
    'loginAction' => [
        'controller' => 'Users',
        'action' => 'login',
    ],
    'authenticate' => [
        'Form' => [
            'userModel' => 'Users',
            'fields' => [
                'username' => 'username',
                'password' => 'password',
            ],
            'contain' => 'Shops', // 3.1 で非推奨
            'scope' => [], // 3.1 で非推奨
            'finder' => 'login',
        ],
    ],
    'authError' => 'ログインをして、ご利用ください。',
    'loginRedirect' => [
        'controller' => 'Users',
        'action' => 'index'
    ],
    'logoutRedirect' => [
        'controller' => 'Users',
        'action' => 'login'
    ]
]);

って感じでやりたいけど、shop_id を渡せない。。
scope や finder 使ってWHEREに固定した条件を追加する事はできるけど username を追加みたいな事ができない。。

で仕方ないので、オリジナルの Authenticate クラスを作成する事にする。

/src/Auth/UserAuthenticate.php

を作成。

中身は

getTableLocator()->get('Users');

        $user = $userTable->query()
            ->contain(['Shops'])
            ->where([
                'Users.code' => $request->getData('code', ''),
                'Shops.code' => $request->getData('shop_code', ''),
            ])
            ->first();

        $password = $request->getData('password', '');
        if ($this->passwordHasher()->check($password, $user->password)) {
            return $user->toArray();
        }

        return false;
    }
}

作成したら、

$this->loadComponent('Auth', [
    'loginAction' => [
        'controller' => 'Users',
        'action' => 'login',
    ],
    'authenticate' => [
        'Form' => [
            'userModel' => 'Users',
            'fields' => [
                'username' => 'username',
                'password' => 'password',
            ],
            'contain' => 'Shops', // 3.1 で非推奨
            'scope' => [], // 3.1 で非推奨
            'finder' => 'login',
        ],
    ],
    'authError' => 'ログインをして、ご利用ください。',
    'loginRedirect' => [
        'controller' => 'Users',
        'action' => 'index'
    ],
    'logoutRedirect' => [
        'controller' => 'Users',
        'action' => 'login'
    ]
]);

の記述を

$this->loadComponent('Auth', [
    'loginAction' => [
        'controller' => 'Users',
        'action' => 'login',
    ],
    'authenticate' => [
        'User' => [],
    ],
    'authError' => 'ログインをして、ご利用ください。',
    'loginRedirect' => [
        'controller' => 'Users',
        'action' => 'index'
    ],
    'logoutRedirect' => [
        'controller' => 'Users',
        'action' => 'login'
    ]
]);

と修正して完了。

Followers