こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

0Auth+PHPで初回ユーザならデータベースに

質問は、初回ユーザならmysqlのデータベースに格納し、初回でなければcallback.phpから../../index.phpにログインしたScreen_nameを表示させたいのですが、どうにもうまくいかず、どなたかご教授して頂けませんでしょうか。
よろしくお願い致します。

<?php
session_start();
require_once('twitteroauth.php');

define('CONSUMER_KEY', 'xxxxx');
define('CONSUMER_SECRET', 'xxxxx');

// getToken.php でセットした oauth_token と一致するかチェック
if ($_SESSION['oauth_token'] !== $_REQUEST['oauth_token']) {
unset($_SESSION);
echo '<a href="getToken.php">token不一致。最初からどうぞ</a>';
exit;
}

// access token 取得
$tw = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET,
$_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
$access_token = $tw->getAccessToken($_REQUEST['oauth_verifier']);

// Twitter の user_id + screen_name(表示名)
$user_id = $access_token['user_id'];
$screen_name = $access_token['screen_name'];

// 初回ユーザかチェックするロジック ここから分からなくなっています。。。。。。。
mysql_connect ('localhost', 'root', 'xxxx');
mysql_select_db('xxxx');
$user_id = get_current_user_id();
if ($user_id == 0) { $sql = "insert into xxxxx values (user_id char(50), screen_name char(255))";
} else { $user_id=$_POST['user_id'];
}

投稿日時 - 2013-12-19 12:35:05

QNo.8392582

すぐに回答ほしいです

質問者が選んだベストアンサー

まず思ったのですが…

>> $sql = "insert into xxxxx values (user_id char(50), screen_name char(255))";

これなんでしょうか。せめてやるならば(SQLインジェクションの脆弱性を無視してもいいなら)

$sql = "insert into xxxxx values (user_id {$user_id}, screen_name '{$screen_name}')";

だと思うのですが…

MySQLのカラムについてですが、CHAR型よりもVARCHAR型の方が望ましいです。

user_id → VARCHAR(19) [PRIMARY KEY に設定]
screen_name → VARCHAR(20)

でいいと思います。
(この先screen_nameの最大長が変わることも見越して)

さて、

>> // 初回ユーザかチェックするロジック ここから分からなくなっています。。。。。。。
>> mysql_connect ('localhost', 'root', 'xxxx');
>> mysql_select_db('xxxx');
>> $user_id = get_current_user_id();
>> if ($user_id == 0) { $sql = "insert into xxxxx values (user_id char(50), screen_name char(255))";
>> } else { $user_id=$_POST['user_id'];
>> }

この部分ですが、これ全部NGです。まず非推奨のMysql関数を使っている時点でダメだし、エラーチェックも行ってないあたりもダメです。

PHPでデータベースに接続するときのまとめ
http://qiita.com/mpyw/items/b00b72c5c95aac573b71

上記ようにPDOをそのまま用いてもいいのですが、そのままだと若干使いにくいために、それを使いやすいように私が拡張したクラスがあるのでぜひ使ってみてください。面倒なオプション設定で基本的に必要なものは自動で設定してくれるのも強みです。

PDO2 / PDOStatement2
https://github.com/Certainist/PDO2

また、twitteroauthの上位互換的なライブラリも自作しているので、こちらも紹介しておきます。twitteroauthと基本的な使い方はほとんど同じですが、それよりも多くの機能をサポートしています。

UltimateOAuth
https://github.com/Certainist/UltimateOAuth

SQL実行の流れとしては、

「user_idが登録済みであればscreen_nameをUPDATE、そうでなければINSERT」

という形を取ります。screen_nameは後から変更できてしまうので、こちら側でも何らかの変更手段が必要となるからです。以下のサンプルソースは全角スペースでインデントしています。

【prepare.php】

<?php

require_once 'UltimateOAuth.php';
session_start();

$_SESSION['uo'] = new UltimateOAuth('xxxx', 'xxxx');
$res = $_SESSION['uo']->post('oauth/request_token');
if (isset($res->errors)) {
 die(sprintf('Error[%d]: %s',
  $res->errors[0]->code,
  $res->errors[0]->message
 ));
}
header('Location: ' . $_SESSION['uo']->getAuthorizeURL());

【callback.php】

<?php

require_once 'UltimateOAuth.php';
require_once 'PDO2.class.php';
require_once 'PDOStatement2.class.php';
session_start();

try {
 
 if (!isset($_SESSION['uo'])) {
  throw new RuntimeException('session timeout', -1);
 }
 if (!isset($_GET['oauth_verifier'])) {
  throw new RuntimeException('no oauth_verifier', -1);
 }
 $res = $_SESSION['uo']->post('oauth/access_token', array(
  'oauth_verifier' => $_GET['oauth_verifier']
 ));
 if (isset($res->errors)) {
  throw new RuntimeException(
   $res->errors[0]->message,
   $res->errors[0]->code
  );
 }
 
 $pdo = new PDO2(
  'mysql:dbname=xxxx;host=localhost;charset=utf8',
  'root',
  'xxxx'
 );
 $sql = implode(' ', array(
  'INSERT INTO xxxx(user_id, screen_name)',
  'VALUES(?, ?)',
  'ON DUPLICATE KEY',
  'UPDATE screen_name = ?',
 ));
 $pdo->prepare($sql)->execute(array(
  $_SESSION['uo']->user_id,
  $_SESSION['uo']->screen_name,
  $_SESSION['uo']->screen_name
 ));
 
 header('Location: http://example.com/index.php');

} catch (PDOException $e) {
 
 echo 'Error[-1]: database error';

} catch (Exception $e) {
 
 printf('Error[%d]: %s',
  $e->getCode(),
  $e->getMessage()
 );

}

【index.php】

if (!isset($_SESSION['uo']->user_id)) {
 die('Error[-1]: Unauthorized');
}
echo 'Hello, ' . $_SESSION['uo']->screen_name;

投稿日時 - 2013-12-19 14:32:37

補足

ご丁寧にありがとうございます。
早速、調べみます。
また追って。質問をするかもしれませんが、ひとまず、本当にありがとうございます。

投稿日時 - 2013-12-19 16:17:51

お礼

To_aru_User様
下記の使わさせて頂いております。
require_once 'UltimateOAuth.php';
require_once 'PDO2.class.php';
require_once 'PDOStatement2.class.php';

またprepare.php,callback.phpも同様に使わせてもらい、挑戦しているのですが、
index.phpの<body>直下に
<?php
if (!isset($_SESSION['uo']->user_id)) {
 die("Error[-1]: Unauthorized");
}
?>
を入れますと、
Fatal error: Call to undefined function  die() と出てしまい、exitを変わりしてみたのですが、同じエラーが出てしまいました。
ちなみに<?php echo 'Hello, ' . $_SESSION['uo']->screen_name; ?>表示させたい所においております。

また初歩的なことなのですが、上記IFを除いてindex.phpからprepare.phpがあるディレクトリにリンクをして、ページが変わると、



Warning: require_once(UltimateOAuth.php): failed to open stream: No such file or directory in /home/users/2/lolipopxxx/web/dist/PHP/prepare.php on line 4

Fatal error: require_once(): Failed opening required 'UltimateOAuth.php' (include_path='.:/usr/local/php5.4/php') in /home/users/2/lolipop.jpxxx/web/dist/PHP/prepare.php on line 4

と表示されてしまいます。ディレクトリーはindex.php以外PHP/の中に全て入れております。

まだcallback.phpまでたどりつけてないのですが、
Parse error: syntax error, unexpected ' if' (T_STRING) line10
 
line 10↓
if (!isset($_SESSION['uo'])) {
  throw new RuntimeException('session timeout', -1);
 }
 if (!isset($_GET['oauth_verifier'])) {
  throw new RuntimeException('no oauth_verifier', -1);
 }
 $res = $_SESSION['uo']->post('oauth/access_token', array(
  'oauth_verifier' => $_GET['oauth_verifier']
 ));
 if (isset($res->errors)) {
  throw new RuntimeException(
   $res->errors[0]->message,
   $res->errors[0]->code
  );
 }


大変ご面倒をおかけて致しまして申し訳ございません。
UltimateoAuthはとても素晴らしそうでぜひ使ってみたいのですが、この未熟者に更なるご教授を頂けましたら幸いです。
お手数をお掛けてして申し訳ございません。。

投稿日時 - 2013-12-19 17:43:49

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

すいません、重要なことを1つ忘れていました。

【○】
require_once 'UltimateOAuth.php';
session_start();

【×】
session_start();
require_once 'UltimateOAuth.php';

セッションにオブジェクトを入れるときは、先のそのクラス定義を読み込んでおかないと復元に失敗します。全てのファイルでこの順番で記述されているかどうかを確認してください。

投稿日時 - 2013-12-21 21:06:41

お礼

To_aru_User様
ご返答ありがとうございます。上記の通りに変更を加えたのですが、同様のエラーメッセージが出てしまい。githubからUltimateOAthのライブラリからやり直し、同サイトのindex.php以外は同説明文のままコードを使ってみました。

全て同じディレクトリに入れており、UltimateOAuth.php

FULL_URL_TO_THIS_FILE = 'ここにはサイト名を入れてます。';
/* You have to fill here! */
const MULTIPLE_REQUEST_KEY_NAME = '____ULTIMATE_OAUTH_MULTIPLE_REQUEST_KEY____';

twitter認証まではうまくいき、dev.twitterでcallback URLの指定先をhttp://サイト名/callback.phpにしております。

To_aru_User様が作成されたのを実行を何度も繰り返していたのですが、

Fatal error: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition &quot;UltimateOAuth&quot; of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in lolipop.jp/web/callback.php on line 23

と表記されてしまいます。
こちらはUltimateOAuth.phpの方で何か修正が必要になるのでしょうか。

お助けに大変感謝しております。

投稿日時 - 2013-12-24 19:21:46

ANo.4

>> 『?』については、?の所にアプデコードを書けばいいんですよね

えーっと、ちょっとこれは違うような・・・

例のまとめのURLにアンカーつけました、この部分をまず重点的に読んでください。
http://qiita.com/mpyw/items/b00b72c5c95aac573b71#2-3

とりあえず「?」を含むものとしてSQLを準備しておき、後からその部分に適切な処理をしていろいろな値を埋め込めるということですね。その「適切な処理」は、こちらが変数の型さえ指定すれば後は全部PDO側がやってくれるのでラクです。

投稿日時 - 2013-12-20 17:17:59

補足

To_aru_User様
お世話になっております。。
認証後、callback.phpに戻ってくるとError[-1]: session timeoutと表示がされてしまいます。
色々と調べてみたのですが、全く分からず、php.iniの設定なのかなとか思ったり。
session.cookie_lifetime = 0 になっていたので、300に変更してApacheを再起動しても、あまり意味がなく、同じエラーメッセージがブラウザに表示されてしまいます。


$pdo = new PDO2('mysql:dbname=LAA0429201-twitter; host=mysql0xxxxx;charset=utf8','LAAxxxxx', 'password');
$sql = implode('', array('INSERT INTO twit (no, user_id, screen_name)', 'VALUES(?, ?, ?)', 'ON DUPLICATE KEY', 'UPDATE screen_name = ?',));
$pdo->prepare($sql)->execute(array($_SESSION['uo']->user_id, $_SESSION['uo']->screen_name, $_SESSION['uo']->screen_name));

とここが問題なのか、問題箇所の特定が出来ておらず、調べているのですが、もし何かご存知であれば、ご教授頂ければ幸いです。

あー

投稿日時 - 2013-12-21 08:56:53

お礼

To_aru_User様

お世話になりっぱなしです。

callback.php
// Check session timeout
if (!isset($_SESSION['uo'])) {
die('Error[-1]: Session timeout.');
}
こちらの記載をコメントアウトしとき、

// Check oauth_verifier
if (!isset($_GET['oauth_verifier'])) {
die('Error[-1]: No oauth_verifier');
}

下記記載のところで、Fatal error: Call to a member function post() on a non-object というエラーが出てしまいます。
// Get access_token
$res = $uo->post('oauth/access_token', array(
'oauth_verifier' => $_GET['oauth_verifier']

prepare.phpでは
$res = $_SESSION['uo']->post('oauth/request_token');
if (isset($res->errors)) {
die(sprintf('Error[%d]: %s',
$res->errors[0]->code,
$res->errors[0]->message
));
}
header('Location: ' . $_SESSION['uo']->getAuthorizeURL());

のままで、大丈夫なのですが。。

UltimateOAuth.phpの所はいじってはなく、下記の部分のみに変更をいたしました。

const FULL_URL_TO_THIS_FILE = 'dist/PHP/UltimateOAuth.php'; /* You have to fill here! */
const MULTIPLE_REQUEST_KEY_NAME = '____ULTIMATE_OAUTH_MULTIPLE_REQUEST_KEY____';

Error[-1]: session timeoutが出てしまうエラーと(ブラウザのキャッシュなどはクリアしてます。)

どうにもこうにも謎が解けず、彷徨っておりました。
何かお分かりでしたらよろしくお願い致します。

そして、たびたびありがとうございます。

投稿日時 - 2013-12-21 15:32:16

ANo.3

>> Fatal error: Call to undefined function  die()

↑明らかに「 die()」って全角スペース入っていますよね・・・w

exit() や die() は基本的な言語構造であり、バージョンによって左右されることはPHP5以降ではあり得ません。
http://php.net/manual/ja/function.exit.php

header関数でLocation指定するときはHTTPから始まる絶対URLにしてください。その際、書式は厳格に守ってください。

○ 'Location: http://...'
× 'Location : http://...'
× 'Location :http://...'

>> もしscreen_nameが変わっていた時に、データベースをアプデしてくれる記述になるのですよね!?

そうですね。SQL文自体はそうなっています。長くて見にくいので、配列として適当に切り分けておき、implode関数で半角スペースを挿入して最後に結合しています。

INSERT ... ON DUPLICATE KEY UPDATE 構文
http://dev.mysql.com/doc/refman/5.1/ja/insert-on-duplicate.html

投稿日時 - 2013-12-20 15:45:53

補足

全角になってました…。顔をから火を吹き出しそなくらい恥ずかしいです。。
Implode関数の所には、半角スペースのみをいれておき、update構文にある『?』にについては、?の所にアプデコードを書けばいいんですよね。

あまりにも初心なので、PHP逆引き辞典を購入しましたw
本当に助かっています。
頂きましたURLを精読したのち、またご質問をさせて頂く事があるかもしれませんが、お忙しい所申し訳ないのですが、
不明点がありました、またご質問させて頂ければなぁと。
感謝だけの言葉だけでは足りず、ハグしたい気分ですw(他意はありませんw)
ちょっと戦ってみます。
本当に感謝、そして、詳しいお方がいらっしゃった事に助かっています。
ありがとうございます。

投稿日時 - 2013-12-20 16:09:39

ANo.2

重要↓

>> 以下のサンプルソースは全角スペースでインデントしています。

OKWaveは半角スペースだとインデントが崩れるので・・・w
テキストエディタの機能で全角スペースを全て半角スペース2個分に置換すればちょうどよくなると思います。

あとindex.phpの訂正だけ・・・

【Before】

if (!isset($_SESSION['uo']->user_id)) {
 die('Error[-1]: Unauthorized');
}
echo 'Hello, ' . $_SESSION['uo']->screen_name;

【After】

<?php

require_once 'UltimateOAuth.php';
session_start();

if (!isset($_SESSION['uo']->user_id)) {
 die('Error[-1]: Unauthorized');
}
echo 'Hello, ' . $_SESSION['uo']->screen_name;


あと

>> Warning: require_once(UltimateOAuth.php): failed to open stream: No such file or directory in /home/users/2/lolipopxxx/web/dist/PHP/prepare.php on line 4


これが出るということはパスがずれていますね。「prepare.php」「callback.php」「UltimateOAuth.php」3ファイルが同一階層
にあることを想定してコードは提示しました。また「index.php」がもし「../../index.php」という位置づけであるならば、当然

require_once 'UltimateOAuth.php';

は(ディレクトリfoo,barを例として)

require_once 'foo/bar/UltimateOAuth.php';

としなければなりません。

投稿日時 - 2013-12-19 21:30:58

補足

To_aru_User様

本当に何から何までありがとうございます。自分も半角やディレクトリーの設定などのミスなどお恥ずかしい限りです。。こちらの問題は解決致しました。ありがとうございます!

ご迷惑ついでに、お伺いをしたいのですが、

beforeに記述されています。
if (!isset($_SESSION['uo']->user_id)) {
 die('Error[-1]: Unauthorized');
}
なのですが、

Fatal error: Call to undefined function  die() とどうしても出てしまいます。
php5.4を使っているのですが、それと関係があるのでしょうか。

また認証する所まではいけました。ただcallback.phpの画面が真っ白でリダイレクトしてくれてないのです。。

require_once 'UltimateOAuth.php';
require_once 'PDO2.class.php';
require_once 'PDOStatement2.class.php';
これらは同じcallback.phpと同じディレクトリーにあるので、そのまましており、

session_start();

try {

if (!isset($_SESSION['uo'])) {
throw new RuntimeException('session timeout', -1);
}
if (!isset($_GET['oauth_verifier'])) {
throw new RuntimeException('no oauth_verifier', -1);
}
$res = $_SESSION['uo']->post('oauth/access_token', array(
'oauth_verifier' => $_GET['oauth_verifier']
));
if (isset($res->errors)) {
throw new RuntimeException(
$res->errors[0]->message,
$res->errors[0]->code
);
}

上記の記載は、そのままにしており、
あとは考えらるのが、明らかに自分のミスが原因だと思われる。

$pdo = new PDO2('mysql:dbname=xxxx;host=localhost;charset=utf8','root', 'password');

//ここから。。。。
$sql = implode(' ', ←混乱なうです。。。
array(INSERT INTO xxxxx '(user_id, screen_name)', 'VALUES( VARCHAR(19), VARCHAR(20))', 'ON DUPLICATE KEY', 'UPDATE screen_name = ?')); ←もしscreen_nameが変わっていた時に、データベースをアプデしてくれる記述になるのですよね!?

$pdo->prepare($sql)->execute(array($_SESSION['uo']->user_id, $_SESSION['uo']->screen_name, $_SESSION['uo']->screen_name));

header('Location: ../../index.php');

} catch (PDOException $e) {

echo 'Error[-1]: database error';

} catch (Exception $e) {

printf('Error[%d]: %s', $e->getCode(), $e->getMessage());

}

あまりにも質問が多く、そして懇切丁寧にご指導して頂いており、本当に申し訳ないです。。
でもとても勉強になり、悪夢からも開放されてきていますw ありがとうございます。

投稿日時 - 2013-12-20 14:44:42

あなたにオススメの質問