環境
- CentOS6.9
- PHP7.2
- CakePHP4.1
- cakephp/authentication 2.3.0
やりたかったこと
公式の認証チュートリアルでは、 Users テーブルを使って、src/Controller 直下にある UsersController 経由でログインするというもので、これはすぐ出来ました。
今回やりたかったのは、①これを管理者用のログイン機能にするのと、プラス、②認証用のユーザーテーブルを users ではなく、administrators に変えること。
①はすぐ出来ましたが、②に手こずりました。
時系列:やったこと
前準備:管理者用のURLでログイン出来るようにした
これは事前準備で、①をするために、 /admin の prefix がある場合に管理画面で処理する用のルートを追加し、Controller/Admin ディレクトリを作って諸々をそちらに移動して、View も同じくディレクトリを移動してあります。
さらに、認証に使うユーザー情報のテーブルを、いずれマルチ認証する場合に備えて、 Users ではなく Administrators に名前変更して、Entity や Table の名前を変えていきます。(UsersController から改名した)AdministratorsController 内でも、リダイレクトパスなどを /admin 付きの URL に変更しました。
(この辺は後でやる気が残ってれば記事に詳細追記します)
ログイン時、エラー
さて、これで準備オーケー。これでログインを試すと、なぜかエラー。
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db_name.users' doesn't exist
Cake\Database\Exception
そらそうだ。
administrators を見に行ってほしいんだもの……。
困ったね。
この、users というのを指定している箇所はどこかなと思って、エラー時の StackTrace をなぞって見ていくと、気になる箇所が。
.
.
.
Authentication\Identifier\Resolver\OrmResolver->find
ROOT/vendor/cakephp/authentication/src/Identifier/PasswordIdentifier.php:154
Authentication\Identifier\PasswordIdentifier->_findIdentity
ROOT/vendor/cakephp/authentication/src/Identifier/PasswordIdentifier.php:99
Authentication\Identifier\PasswordIdentifier->identify
ROOT/vendor/cakephp/authentication/src/Identifier/IdentifierCollection.php:52
.
.
.
怪しい。多分これじゃないか。
ということで、中身拝見。
vendor/cakephp/authentication/src/Identifier/Resolver/OrmResolver.php
これの中身見ると、
class OrmResolver implements ResolverInterface
{
.
.
.
protected $_defaultConfig = [
'userModel' => 'Users', #←あった。めっちゃ Users って書いてる
'finder' => 'all',
];
/**
* Constructor.
*
* @param array $config Config array.
*/
public function __construct(array $config = [])
{
$this->setConfig($config);
}
/**
* @inheritDoc
*/
public function find(array $conditions, $type = self::TYPE_AND)
{
$table = $this->getTableLocator()->get($this->_config['userModel']);
$query = $table->query();
$finders = (array)$this->_config['finder'];
.
.
.
}
ふむ、なるほど。
デフォルトで Users を見に行くようなので、オプションで指定してやる必要がありそうです。
ということで、
CakePHP4のミドルウエアを使った認証で別テーブルを参照(authentication)
こちらを参照し、以下のようになりました。
class Application extends BaseApplication implements AuthenticationServiceProviderInterface
{
.
.
.
public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
{
$authenticationService = new AuthenticationService([
'unauthenticatedRedirect' => Router::url('/admin/administrators/login'),
'queryParam' => 'redirect',
]);
// identifiers を読み込み、email と password のフィールドを確認します
$authenticationService->loadIdentifier('Authentication.Password', [
'resolver'=>[ #←追記
'className' => 'Authentication.Orm', #←追記
'userModel' => 'Administrators' #←追記 ここで Administrators を指定
], #←追記
'fields' => [
'username' => 'email',
'password' => 'password',
]
]);
.
.
.
これで無事、administrators テーブルを使ったログインが出来るようになりました。