データ入力条件でのデータベース作成の問題

このQ&Aのポイント
  • データ入力条件でのデータベース作成に関する問題が発生しています。
  • RSSよりリンクとタイトルを読み込み、DBに入力する際に重複を防ぐ方法を検討中です。
  • 現在の方法では$res[$i]が常にtrueになり、重複の判別ができないため、登録がうまくいかない状況です。
回答を見る
  • ベストアンサー

データ入力条件

RSSを元にデータベースを作成予定です。 $db=new PDO("mysql:host=localhost;dbname=database",$dbuser,$dbpass); $rss=simplexml_load_file("http://rss.rssad.jp/rss/itmlifestyle/2.0/camera.xml"); for($i=0;$i<count($rss->item);$i++) { $title[$i]=$rss->item[$i]->title;//タイトル抽出 $url[$i]=$rss->item[$i]->link;//リンク先抽出   //▼▼▼▼▼検索させるクエリ発行▼▼▼▼▼ $search=$db->prepare("SELECT * FROM rss where title = ?"); $res[$i]=$search->execute(array($title[$i]));   //検索結果が偽の場合 if(!$res[$i]) { $INSERT=$db->prepare("INSERT INTO rss(url,title) VALUES(?,?)"); $INSERT->execute(array($url[$i],$title[$i])); } } RSSよりリンクとタイトルを読み込み、DBに入力する際、既に登録されている値(タイトル)がある場合は重複させないよう、登録せず、無い場合は登録をさせようとしています。 こちらが上手く作動しません。 何処がおかしいのか大体探ってみると$res[$i]の部分がいつもtrueの真偽値になっており、判別が出来ず、登録も滅茶苦茶になってしまいます。 登録されている値と重複する場合は登録せず、新しい値のみを登録させることは出来ますよね? 持ってくるRSSの情報が多いと失敗するのか、これまた1個づつなら可能なんでしょうか? ややこやしいですが、どちらかご教授お願い致します。

  • PHP
  • 回答数4
  • ありがとう数1

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

  • ベストアンサー
  • duron
  • ベストアンサー率77% (73/94)
回答No.1

PDOはほとんど触ったことが無いので違っていましたらごめんなさい。 環境が無いので動作検証もしてません。 http://www.php.net/manual/ja/pdostatement.execute.php $search->executeの結果返ってくるのはSQLの実行が成功したか失敗したかです。 つまり該当があろうがなかろうがSQLの文法が間違っていないならばTRUEになります。 該当件数を得るならば実行結果をチェックする必要があります。 該当件数を得るために以下のようにしてみてください。   //▼▼▼▼▼検索させるクエリ発行▼▼▼▼▼ $search=$db->prepare("SELECT count(*) as cnt FROM rss where title = ?"); $res[$i]=$search->execute(array($title[$i])); if($res[$i]) { $values=$search->fetch(PDO::FETCH_ASSOC);   //該当件数が0件の場合 if($values["cnt"]==0) 後、タイトルは別記事でも重複する可能性があるのでURL(もしくは他にチェックできる項目)を元に 重複チェックをしたほうがよいかと思います。

atlantic32
質問者

お礼

有難う御座いました。「教えてgoo」を今見ました。 「つまり該当があろうがなかろうがSQLの文法が間違っていないならばTRUEになります。」 これが大事でした。いつもTRUEになるのは当然です。貴方の仰るように実行結果を チェックすることで入力の判別が可能になりました。 解決しました、有難う御座います。

その他の回答 (3)

  • duron
  • ベストアンサー率77% (73/94)
回答No.4

ごめんなさい、No.3の回答中の if(!$res) は if($res) が正しいです。

  • duron
  • ベストアンサー率77% (73/94)
回答No.3

No.1の回答がサポートで内容を確認中ということで現在表示されて 無いのでもう一回書き込んでみようと思います。 (確認中になったのはリンクに「.exe」が含まれてたのが原因なのかな?) No.1でも書きましたがPDOはほとんど扱ったことがないので間違ってたらごめんなさい。 実行環境がないので動作確認もしていないのでおかしなところがあったら直してください。 PDOStatement::executeで戻ってくる値はSQLの実行が成功したか失敗したかというものです。 つまりSQLが文法的に間違っていない場合にはtrueが返ってくることになります。 No.2さんへの補足にあるPDO::queryも同様にSQL異常で無い限りFALSEとはなりません。 ですので該当が何件あったか?という条件でチェックする必要があります。 そこで以下のように変えてみてください。 foreach($rss->item as $data) { $url=$data->link; $title=$data->title; $select="SELECT count(*) as cnt FROM rss where url='$url'"; $res=$db->query($select); if(!$res) { $values=$res->fetch(PDO::FETCH_ASSOC); if($values["cnt"]==0) { $INSERT=$db->prepare("INSERT INTO rss(url,title) VALUES(?,?)"); $INSERT->execute(array($url,$title)); } } }

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.2

forのLoopn中で、そこまで添え字を使う必要があるんでしょうか?$titleや$urlや$resをあとで配列の状態で使うのなら仕方ありませんけど、少なくとも$resまで配列になっているのは(そのときにチェックするだけなので)意味がないと思います。 for($i=0;$i<count($rss->item);$i++) { $title=$rss->item[$i]->title;//タイトル抽出 $url=$rss->item[$i]->link;//リンク先抽出   //▼▼▼▼▼検索させるクエリ発行▼▼▼▼▼ $search=$db->prepare("SELECT * FROM rss where title = ?"); $res=$search->execute($title);   //検索結果が偽の場合 if(!$res) { $INSERT=$db->prepare("INSERT INTO rss(url,title) VALUES(?,?)"); $INSERT->execute(array($url,$title)); } }

atlantic32
質問者

補足

添字の部分は最近付けてみたのですが確かに結果は変わりませんでした。 下記内容が何故作動しないのかわかりません。論理的には合ってるはずなのですが。 再度ご覧頂ますよう、宜しくお願い致します。 $rss=simplexml_load_file("http://rss.rssad.jp/rss/impresswatch/pcwatch.rdf"); foreach($rss->item as $data) { $url=$data->link; $title=$data->title; $select="SELECT * FROM rss where url='$url'"; $res=$db->query($select); if(!$res){$insert=INSERT INTO rss(title,url) VALUES(?,?);execute(array($title,$url));} }

関連するQ&A

  • executeの実行が一回しかされない

    foreach ($rss->channel->item as $val) { $title = $val->title; $link = $val->link; $description = $val->description; $pubDate = $val->pubDate; $dccreator = $val->dccreator $stmt = $dbh->prepare("insert into rss (title,link,description,pubDate,dccreator) values(?,?,?,?,?)"); $stmt->execute(array($title,$link,$description,$pubDate,$dccreator)); } 上のような感じでexecuteの実行をループさせようとしています。 しかし最初の一回しか実行されません。(DBへの書き込みが最初の一度しかされません) すいませんが、何かアドバイスいただけませんでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • foreachのスコープ

    while(0<$i<count($html)) { foreach($html->find('title') as $title) { global $title; } foreach($html->find('img a')as $url) { global $link=$url->href; $link=mb_convert_encoding($url,"utf8","euc-jp"); var_dump($link);//この変数をスコープ範囲外でDBに登録したい } $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); $stt=$db->prepare('insert into links(name,url) VALUES(?,?)'); $stt->execute(array($title,$link)); } ------------------------------------------------------------------------- 上記を行いたくコードを記述してましたが$linksの部分に何もなく、DB登録することが出来ませんでした。原因を探すために検索したところ、関数の範囲内の変数のスコープに問題があることがわかりました。外部から内部変数へのアクセス(参照)は不可能なのでしょうか?現在のままだと「$url」が文字列ではない状態なので登録できないと考えております。事実文字列の「$title」はDBに登録出来るのですが$linkのみ値が何も入ってない状態で登録されてしまいます。 スコープの範囲内であれば当然var_dump($link)は表示されます。 使ってるライブラリは「simple html dom parser」で、抽出は完了しています。 この「$link」というのは文字列ではない状態なので文字列変換させる関数に直せばDB登録できるのでしょうか?それならばstrvalまたは__toString関数を他に作っておいてそれを使えば可能なのでしょうか? どなたかご教授頂けませんでしょうか?

    • 締切済み
    • PHP
  • PEAR でprepareメソッドがエラーに

    初心者です。 今テストで下記構文を試しましたがエラーになります。 prepareがインストールされていないのでしょうか? どなたかご教授お願いします。 エラー内容↓ Fatal error: Call to undefined method DB_Error::prepare() テスト構文↓ <?php require_once("DB.php"); $db=DB::connect("sqlite://localhost/samples.db"); $stt=$db->prepare("CREATE TABLE article (url,title,published)"); $stt=$db->execute(); $db->disconnect($stt); ?>

    • 締切済み
    • PHP
  • PerlからDB接続し、データ登録時のエラー処理について

    PerlからDB接続し、データ登録時のエラー処理について DBにデータを登録するときにエラー処理を加えたいと思っていますが、 色んなサイトを参考にさせて頂いて、下記のようにしてみたのですが うまくできません。 $sth = $db->prepare(" INSERT INTO DBNAME (hinmei,su,tani,tuikabi) VALUES($hinmei,$su,$tani,$hiduke) "); if(!$sth->execute){  print "接続エラー";  exit; } または、 $sth = $db->prepare(" INSERT INTO DBNAME (hinmei,su,tani,tuikabi) VALUES($hinmei,$su,$tani,$hiduke) "); $sth->execute or &error('DBに登録出来ません'); 両方とも登録出来なければエラーメッセージを出すように してみたのですが、キー項目が同じものを登録しようとすると $sth->execute この部分でとまってしまうらしく、次の処理に行きません。 もちろん、キー項目が同じでなければDBに登録出来ます。 どうすればエラー処理の設定ができるでしょうか。 教えてください。 お願いします。

    • ベストアンサー
    • Perl
  • mysql データベース処理が途中で失敗したら?

    お世話になります。 現在、mysqlのデータベースを使ったphpプログラムを書いているのですが、 以下のように、続けて2つのデータベース処理を記述している部分があります。 $db=connectDb(); //処理1 $st1=$db->prepare("update table1 set title=:title where id=:id1 limit 1"); $st1->execute(array(":title"=>$title,":id"=>$id)); //処理2 $st2=$db->prepare("update table2 set image=:image where id=:id2 limit 1"); $st2->execute(array(":image"=>$image,":id"=>$id2)); db=NULL; ここで質問があります。 このような記述ですとなんらかの理由により、例えば、 「処理1のアップデート処理は成功したが、 次の処理2のアップデート処理には失敗してしまった。」 というような問題は起きることがあるのでしょうか? 起きることがある場合、それに備えてどのような記述をすれば対応できるでしょうか? ご存知の方、ご回答いただければ幸いです。 よろしくお願い致します。

    • ベストアンサー
    • PHP
  • RSSに関して

    こんばんは。お世話になっております。 只今、テスト的に以下のサイトのソースを参考に、登録していただいた方のブログの一覧表示(更新題名が1件ずつ)が出来るように組んでいるのですが、非常に重たく、他に上手いやり方がある?などと色々と試行錯誤を繰り返している状況です。 http://works.xrea.jp/headline.php イメージ的に、登録してくれた会員のブログを、ブログランキングサイトのように、検索一覧として1件ずつ更新記事(題名)を表示させたいと考えてます。 ソースの流れは、 while($row = mysql_fetch_array($res, MYSQL_ASSOC)){  $url = $row["url"];  require("./rss_index/rss-test.php");  ・  ・ 以上、検索ファイル 以下、rss-test.php <?php require_once 'rss_fetch.inc'; $url = $url; $rss = fetch_rss($url); $title = $rss->channel['title']; $title = mb_convert_encoding($title, "EUC-JP", "auto"); echo "<h5>$title</h5>\n"; $rss->items = array_slice($rss->items, 0, 1); foreach ($rss->items as $item ) { $title = $item[title]; $title = mb_convert_encoding($title, "EUC-JP", "auto"); $url = $item[link]; echo "<li><a href=\"$url\">$title</a></li>\n"; } ?> 以上、お忙しい中恐縮ですが、ご指摘も含めアドバイスなど頂けたら幸いです。宜しくお願い致します。

    • ベストアンサー
    • PHP
  • PDOで取得される値がすべて文字列になる

    xamppを標準インストールした環境にてPHPのPDOを利用したデータベース処理を試しているのですが、SELECTで取得した値がすべて文字列として返されます。 $db = new PDO("sqlite:sample.db"); $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $rs = $db->query("select 1 as res"); $rs = $rs->fetch(); 結果: array(1) ( [res] => (string) 1 ) これに加え、やや強引なテストを行ってみたのですが、こちらも結果は同じく文字列となりました $db = new PDO("sqlite:sample.db"); $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); $rs = $db->prepare("select ? as res"); $rs->bindValue(1, 1, PDO::PARAM_INT); $rs->execute(); $rs = $rs->fetch(); この現象を回避するにはどのようにすればよいでしょうか。

    • ベストアンサー
    • PHP
  • SQLインジェクション対策

    SQLインジェクション対策として、変数を直接SQLに埋め込むのではなく、PDOのprepareメソッドを利用して作成したステートメントに値をバインドする形式にする場合、ユーザー定義関数をどのように 修正すればいいですか? function update_item_stock($db, $item_id, $stock){ $sql = " UPDATE items SET stock = {$stock} WHERE item_id = {$item_id} LIMIT 1"; return execute_query($db, $sql); } function execute_query($db, $sql, $params = array()){ try{ $stmt = $db->prepare($sql); return $stmt->execute($params); }catch(PDOException $e){ set_error('更新に失敗しました。'); } return false; } 上記のユーザー定義関数を下記のようにbindValueを用いて表す場合、$stmt->bindValueの部分を 上記のどこに追加すればいいですか? try { $sql = 'UPDATE item_stock SET stock = ?, update_date = ? WHERE item_id = ?'; $stmt = $db->prepare($sql); $stmt->bindValue(1, $update_stock, PDO::PARAM_INT); $stmt->bindValue(2, $date, PDO::PARAM_STR); $stmt->bindValue(3, $item_id, PDO::PARAM_INT); $stmt->execute(); $complete_msg[] = '在庫変更に成功しました。'; } catch (PDOException $e) { $err_msg[] = '更新に失敗しました。理由:' . $e->getMessage(); }

    • 締切済み
    • PHP
  • MDB2 [Call to undefined method MDB2

    MDB2 [Call to undefined method MDB2_Error::execute()] 以下のようなMDB2を利用したSELECT文を書きましたが、 最終行で、 Call to undefined method MDB2_Error::execute() が出ます。 どのように修正すれば良いでしょうか? ===================================================================================== require_once('/usr/share/pear/PEAR/MDB2.php'); $db=MDB2::connect('mysqli://【user】:【password】@localhost/【dbname】?charset=utf8'); if(PEAR::isError($db)){ die($db->getMessage()); } $sql = 'select * from user where name=? and password=?'; $types = array('text','text'); $stmt=$db->prepare($sql, $type, TRUE); $data = array('guest' , 'guest'); $res = $stmt->execute($data); ===================================================================================== 下から3行目の$stmtがMDB2_Errorオブジェクトなのまでは分かるのですが、 どう対処すればよいかが不明です。 宜しくお願いします。

    • ベストアンサー
    • PHP
  • PHP mysql の戻り値

    PHP内にて、下記の処理、上手くINSERTはされているのですが、 デバッグで埋めた print のところで res1 == Object id #6 が表示されます。 (1) Object id #6とはなんでしょうか? (2)正常、異常のときの $stmt の戻り値は何が返りますか?   (3)正常、異常のときの $res  の戻り値は何が返りますか? ~~~(一部抜粋)~~~ $sql = "insert into thread ( id, name, insert_datetime ) values (?, ? , now())"; $stmt = self::$_conn->prepare($sql); $res = $stmt->execute(array($id_mx,$this->get('name'))); print "res1 == ".$res."</br>"; die_if_dberror($res); ~~~~~~~~~~~

    • ベストアンサー
    • PHP

専門家に質問してみよう