CakePHP2とComposerでFacebookログインを実装するまで

みなさんあけましておめでとうございます!
2ヶ月くらい更新してなかったですが、ブログは書き続けてたほうがいいなぁと思っていたので新年からまた書き始めます!

それでは早速書いていきましょう。

最近Composerを使ってCakePHPでFacebookログインを実装したので、そこまでの流れをまとめておこうと思います。

Composerで必要なものをインストールする

composer.jsonから作っていきましょう。

CakePHPFacebook PHP SDKをインストールするので以下のように書けばインストール出来ます。

{
    "name": "facebook-login",
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear.cakephp.org"
        }
    ],
    "require": {
        "pear-cakephp/cakephp": "2.4.4",
        "facebook/php-sdk": "dev-master"
    }
}

composer.pharをダウンロードしてパッケージをインストールしていきます。

$ curl -s http://getcomposer.org/installer | php
$ php composer.phar install

Bakeでプロジェクトを作成します。

$ vendor/bin/cake bake project $PWD --empty

これでブラウザからアクセスすると、いつもの緑画面が出てくると思います。

ここまでで大方終了しましたが忘れちゃいけないので CAKE_CORE_INCLUDE_PATH を書き換えること。

3箇所書き換えていきましょう。

webroot/index.php

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . APP_DIR . DS . 'vendor' . DS . 'pear-pear.cakephp.org' . DS . 'CakePHP');

webroot/test.php

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . APP_DIR . DS . 'vendor' . DS . 'pear-pear.cakephp.org' . DS . 'CakePHP');

Console/cake.php

$ds = DIRECTORY_SEPARATOR;
$dispatcher = 'Cake' . $ds . 'Console' . $ds . 'ShellDispatcher.php';

if (function_exists('ini_set')) {
    $root = dirname(dirname(__FILE__));

    // the following line differs from its sibling
    // /app/Console/cake.php
    ini_set('include_path', $root . $ds . 'vendor' . $ds . 'pear-pear.cakephp.org' . $ds . 'CakePHP' . PATH_SEPARATOR . ini_get('include_path'));
}

if (!include $dispatcher) {
    trigger_error('Could not locate CakePHP core files.', E_USER_ERROR);
}
unset($paths, $path, $dispatcher, $root, $ds);

return ShellDispatcher::run($argv);

最後にデータベースをbakeして終了っと!

$ Console/cake bake db_config

実装前の準備をする(Facebookアプリ作成、SDKの読み込み、データベース等)

次にFacebookアプリやFacebookSDKの読み込み、データベースの作成等を行っていきます。

以下のURLに飛び、Facebookアプリを「新規作成」し、アプリIDとシークレットをゲットしておいてください!

次にcomposerでいれたFacebook PHP SDKを読み込んでいきます。
PagesController.php で読み込んでいきましょう。

PagesController.php


最後にデータベースです。
今回は Admin テーブルを作成しその中にログインに必要な情報を事前に入れておこうと思います。
実際に試す場合は自分のFacebookIDを入れておいてください。

CREATE TABLE IF NOT EXISTS `admin` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `facebook_id` varchar(128) NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

INSERT INTO `admin_user` (`id`, `facebook_id`, `created`, `modified`) VALUES
(1, '自分のFacebookID', NOW(), NOW());

最後の最後に! routes.php 内でPagesControllerのルーティングが定められているのでそれをコメントアウトしておきます。

    // Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));

これで終了です。やっと本題にいきましょう!

Facebookログインを実装していく

さて、やっと本題です。
ログインの流れとしては、

  • ログインボタンクリック
  • Facebook側で認証をする
  • 認証後リダイレクト先でFacebookIDが取れ、データベース内にそのIDがあればログインを完了させマイページに飛ばす

こんな感じでやっていこうと思います。

一気にいきます。PagesController.phpにがばっと書いていきます。

PagesController.php

 [
            'authenticate' => [
                'Form' => [
                    'userModel' => 'Admin'
                ]
            ],
            // ログインページ
            'loginAction' => ['controller' => 'pages', 'action' => 'index'],
            // ログイン後リダイレクトページ
            'loginRedirect' => ['controller' => 'pages', 'action' => 'my'],
            // ログアウト後リダイレクト先
            'logoutRedirect' => ['controller' => 'pages', 'action' => 'index'],
            // エラーメッセージ
            'authError' => 'Admin Only'
        ]
    ];

    public function beforeFilter(){
        $this->facebook = new Facebook([
            'appId' => '取得したAppId',
            'secret' => '取得したAppSecret',
            'cookie' => true
        ]);
        $this->Auth->allow('index', 'login');
    }

    protected function _authFacebook(){
        $login_url = $this->facebook->getLoginUrl(['redirect_uri' => Router::fullBaseUrl() . Router::url(['controller'=>'pages', 'action'=>'login'])]);
        return $this->redirect($login_url);
    }

    public function login(){
        $this->autoRender = false;
        $fb_id = $this->facebook->getUser();
        $login_info = ClassRegistry::init('Admin')->find('first', ['conditions' => ['Admin.facebook_id' => $fb_id]]);
        if(isset($login_info)){
            if($this->Auth->login($login_info['Admin'])){
                return $this->redirect(['action' => 'my']);
            } else {
                return $this->redirect(['action' => 'index']);
            }
        } else {
            return $this->redirect(['action' => 'index']);
        }
    }

    public function logout(){
        $this->Auth->logout();
        return $this->redirect(['action' => 'index']);
    }

    public function index(){
        if($this->Auth->loggedIn()){
            return $this->redirect(['action' => 'my']);
        }
        if($this->request->is('post')){
            $this->_authFacebook();
        }
    }

    public function my(){

    }

}

わからなければ質問なり公式ドキュメントを参照してください!!!

Modelのフォルダ内に Admin.php を下記のような感じで作成します。


Viewは index.ctpmy.ctp を作ります。

index.ctp

Form->create('Admin', ['method' => 'post']);?>

Form->button('Facebookログイン');?>

my.ctp

マイページ

Html->link('ログアウト', ['controller'=>'pages', 'action'=>'logout']);?>

これでFacebookログインが実装できました!!

最後に

いかがでしたでしょうか。
なんとなくの流れは理解出来たかなぁと思います。
何かわからない点がありましたらコメントやTwitterで聞いていただければと思います!

CakePHP本が続々出ていますね。