Facebook PHP SDKでFacebookページにアルバム作成、写真・動画投稿などを実装する


Facebook SDKのバージョンアップが激しく、最新の情報がなかったのでメモ。
細かいところは端折ってます。

## 想定環境

OS : Mac OS X
PHPバージョン : 5.6.17
Graph API バージョン : v2.9
Facebook PHP SDK バージョン : v5.5.0


## Facebook PHP SDKをゲットする

```bash:sample
$ composer self-update
$ composer require facebook/graph-sdk
```
index.phpとかをつっこんでるディレクトリで上記を実行。

ちなみにSDKの詳細ドキュメントは下記。
https://developers.facebook.com/docs/php/gettingstarted

## 該当アプリのapp_id, app_secretを確認

下記より該当のアプリを選択、ダッシュボードにある「アプリID」と「app secret」を確認。
https://developers.facebook.com/apps/


## 管理しているFacebookページのアクセストークンを取得

これが一番キモかも。

自分が管理しているFacebookページのアクセストークンの取得は、
以下の手順で行います。

#### グラフAPIエクスプローラをひらく
https://developers.facebook.com/tools/explorer/

#### 利用アプリを選択
「アプリ」で使用するアプリを選択
※ ここがGraph API Explorerのままにしておくと"You don't have permission to edit this photo or album"とか色々出て死にます

#### 利用するFacebookページを選択
「アクセストークン：」の右側にある「トークン...」を開き、
「ページアクセストークン」一覧の下にある、
利用したいFacebookページを選択。

#### トークンが発行されます
 「アクセストークン:」右側のテキストボックスに、
該当Facebookページのアクセストークンが発行されます。

ちなみに、アクセストークンデバッガーで期限とかも確認可能。
https://developers.facebook.com/tools/debug/accesstoken/

無期限の方法を知りたい方は下記参照すると良さそう。
（ワタシタメシテナイ）
https://gist.github.com/xl1/fe779a817a9d4938193d


## 便利クラス

```php:FacebookAppUtil.php
require_once __DIR__ . '/vendor/autoload.php';

/**
 * Facebook SDKをちょっとだけ使いやすくするクラス
 */
class FacebookAppUtil
{
  const APP_ID = 'APP_IDをここにいれてください';
  const APP_SECRET = 'APP_SECRETをここにいれてください';
  const REDIRECT_URI = '認証後のリダイレクト先をここに入れてください';

  var $facebook;
  var $accessToken;

  /**
   * コンストラクタ
   */
  public function __construct()
  {
    $this->facebook = new Facebook\Facebook(
      array(
        'app_id'  => self::APP_ID,
        'app_secret' => self::APP_SECRET,
        //'cookie' => true,
        'default_graph_version' => 'v2.9',
        'default_access_token' => $_SESSION['facebook_access_token'],
        //'enable_beta_mode' => true,
      )
    );
  }

  /**
   * ログイン実行
   */
  public function login()
  {
    $helper = $this->facebook->getRedirectLoginHelper();
    if (isset($_SESSION['facebook_access_token'])) {
      $this->accessToken = $_SESSION['facebook_access_token'];
    }
    else {
      $token = $helper->getAccessToken();
      if (empty($token)) {
        $url = $helper->getLoginUrl(self::REDIRECT_URI);
        echo "<script type='text/javascript'>top.location.href = '$url';</script>";
        exit;
      }
      else {
        $this->accessToken = $token;
        $_SESSION['facebook_access_token'] = $token;
      }
    }

    return true;
  }

  /**
   * Facebookのインスタンス取得
   */
  public function getFacebook()
  {
    return $this->facebook;
  }

  //////////////////////////////////////////////////////////////////////////////////////////
  // read
  //////////////////////////////////////////////////////////////////////////////////////////
  /**
   * 自分の情報取得
   * $targetは、FacebookページIDなども指定可能
   */
  public function getMyInfo($target = 'me', $fields = 'id,name')
  {
    //$fields = 'id,name';//email,gender,link,locale,name,timezone,updated_time,verified,last_name,first_name,middle_name,work,posts,photos';
    //?fields=albums.limit(5){name, photos.limit(2)}
    $response = $this->facebook->get('/' . $target . '/?fields=' . $fields, $this->accessToken);
    return $response->getGraphUser();
  }

  /**
   * フィード一覧取得
   * $targetは、FacebookページIDなども指定可能
   */
  public function getFeeds($target = 'me', $options = 'limit=10') {
    $response = $this->facebook->get('/' . $target . '/feed?' . $options, $this->accessToken);
    $body = json_decode($response->getBody())->data;
    return $body;
  }

  /**
   * アルバム一覧取得
   * $targetは、FacebookページIDなども指定可能
   */
  public function getAlbums($target = 'me') {
    $response = $this->facebook->get('/' . $target . '/albums?fields=name,picture,created_time', $this->accessToken);
    $body = json_decode($response->getBody())->data;
    return $body;
  }

  /**
   * 写真一覧取得
   * $targetは、アルバムIDなどの指定も可能
   */
  public function getPhotos($target = 'me') {
    $response = $this->facebook->get('/' . $target . '/photos?fields=picture,created_time', $this->accessToken);
    $body = json_decode($response->getBody())->data;
    return $body;
  }

  /**
   * アルバムの写真の詳細情報取得
   * TODO: 現状はオリジナルサイズをかえすようにしてる
   */
  public function getPhotoInfo($photoID = null) {
    $response = $this->facebook->get('/' . $photoID . '/picture?type=normal', $this->accessToken);
    $headers = $response->getHeaders();
    return $headers['Location'];
  }

  //////////////////////////////////////////////////////////////////////////////////////////
  // write
  //////////////////////////////////////////////////////////////////////////////////////////
  /**
   * 写真を投稿
   */
  public function postPhoto($target = 'me', $data = array())
  {
    try {
      $response = $this->facebook->post('/' . $target . '/photos', $data, $this->accessToken);
    }
    catch(Facebook\Exceptions\FacebookResponseException $e) {
      echo 'Graph returned an error: ' . $e->getMessage();
      exit;
    }
    catch(Facebook\Exceptions\FacebookSDKException $e) {
      echo 'Facebook SDK returned an error: ' . $e->getMessage();
      exit;
    }
    return $response;
  }

  /**
   * 動画を投稿
   */
  public function postVideo($target = 'me', $data = array())
  {
    try {
      $response = $this->facebook->post('/' . $target . '/videos', $data, $this->accessToken);
    }
    catch(Facebook\Exceptions\FacebookResponseException $e) {
      echo 'Graph returned an error: ' . $e->getMessage();
      exit;
    }
    catch(Facebook\Exceptions\FacebookSDKException $e) {
      echo 'Facebook SDK returned an error: ' . $e->getMessage();
      exit;
    }
    //$graphNode = $response->getGraphNode();
    //echo 'Video ID: ' . $graphNode['id'];
    return $response;
  }

  /**
   * アルバムを作成
   */
  public function createAlbum($target = 'me', $data = array())
  {
    try {
      $response = $this->facebook->post('/' . $target . '/albums', $data, $this->accessToken);
    }
    catch(Facebook\Exceptions\FacebookResponseException $e) {
      echo 'Graph returned an error: ' . $e->getMessage();
      exit;
    }
    catch(Facebook\Exceptions\FacebookSDKException $e) {
      echo 'Facebook SDK returned an error: ' . $e->getMessage();
      exit;
    }
    //$graphNode = $response->getGraphNode();
    //echo 'Album ID: ' . $graphNode['id'];
    return $response;
  }
}
```

## テストコード

```php:index.php
{
  $FB_PAGE_ID = 'FacebookページのIDをここにいれる';
  $ALBUM_ID = 'アルバムのIDをここにいれる';

  session_start();

  // Facebookページをユーザーとして投稿するためのアクセストークン
  $_SESSION['facebook_access_token'] = 'Facebookページのアクセストークンをここにいれてください';

  // セッション開始
  $fb = new FacebookAppUtil();

  // ログイン
  // セッションを直接指定しているので現状不要
  // 普通のログイン機構を採用する場合はコメントアウト外してください。
  //$fb->login();

  // 情報取得
  $me = $fb->getMyInfo();
  var_dump($me);

  // フィード一覧取得
  $feeds = $fb->getFeeds();
  var_dump($feeds);

  // アルバム一覧取得
  $albums = $fb->getAlbums($FB_PAGE_ID);
  foreach ($albums as $album) {
    echo '<h1>', $album->name, '(', $album->id, ')</h1>';

    // アルバム内の写真一覧取得
    $photos = $fb->getPhotos($album->id);
    foreach ($photos as $photo) {
      // 大きいサイズ
      //$largePhotoPath = $fb->getPhotoInfo($photo->id);
      //echo '<img src="', $largePhotoPath, '" />&nbsp;';

      // サムネサイズ
      echo '<img src="', $photo->picture, '" />&nbsp;', $photo->id, '<br />';
    }
  }

  // アルバムを作成
  $data = array(
    'message'=> 'Album desc',
    'name'=> 'Album name22'
  );
  $res= $fb->createAlbum($FB_PAGE_ID, $data);
  //var_dump($res);

  // 写真をポスト
  $data = [
      'message' => 'test2 light',
      //'source' => $fb->facebook->fileToUpload('img_teck_07.png'),
      'url' => 'http://sorauta.net/wp-content/uploads/2017/02/light_pet_5.jpg',
  ];
  $res = $fb->postPhoto($FB_PAGE_ID, $data);
  //var_dump($res);

  // 動画をポスト
  $data = [
    'title' => 'My Foo Video',
    'description' => 'description.',
    'source' => $fb->facebook->videoToUpload('new.mp4'),
  ];
  $res = $fb->postVideo($FB_PAGE_ID, $data);
  //var_dump($res);
}
```

これで現状のだいたいのことはできる気がするます！
なんか間違ってたら教えてください。

## おまけ

#### FacebookページのページID確認方法

該当のFacebookページを開き、左にある「ページ情報」を開く
https://www.facebook.com/non.classic.inc/

管理しているFacebookページであれば、
下部に「ページID」というのが書いてある。
https://www.facebook.com/pg/non.classic.inc/about/

#### アルバムIDの確認方法

適当なアルバムページ開くと、引数にalbum_idがあるのでそれを取得。
↓こんなかんじ
https://www.facebook.com/2148445985380979/photos/?tab=album&album_id=2156938141198430