- ベストアンサー
RSSをデータベースに格納できない
- 昨日教えていただいたコードで格納して表示するところまで成功しました。自分の不注意でデータベースネームと違う、新規作成したテーブルに格納していたため起こったエラーでした。申し訳ありません。
- 再度全体のコードと組み合わせてみたのですがエラーが起こり困っております。Uncaught Error: Call to a member function insert() on null
- <?php $url1 = [ 'http://blog.livedoor.jp/dqnplus/index.rdf', 'http://alfalfalfa.com/index.rdf', 'http://himasoku.com/index.rdf', ]; foreach ($url1 as $url) { $count = 0; $rss = simplexml_load_file($url); foreach ($rss->item as $item) { if ($count >= 8) { break; } ++$count; $title = (string) $item->title; //「$item->title」だけではうまくいかないのでstringにキャスト $link = (string) $item->link; //以下同じ $thumb = (string) $item->thumb->url; $content = (string) $item->description; $wpdb->insert('rssfeed', ['title' => $title, 'link' => $link, 'thumb' => $thumb, 'content' => $content], ['%s', '%s', '%s', '%s']); } } $results = $wpdb->get_results('SELECT * FROM rssfeed'); foreach ($results as $item) { echo $item->title.'<br>'; } ?> <?php $wpdb->show_errors(); ?>
- みんなの回答 (70)
- 専門家の回答
質問者が選んだベストアンサー
お礼 2022/02/09 18:47 ・cronを同じサイトで複数実装してもエラーにはならないでしょうか? WordPressのCronを試してみました。 CronスケジュールひとつにCronイベントを複数登録できました。 エラーにはならいようです。
その他の回答 (69)
- dell_OK
- ベストアンサー率13% (766/5721)
補足 2022/01/23 21:29 ページングは画面表示が整ってからと思っていたのでLIMITのテストはしていませんでした。 このエラーについては、LIMITがMySQL独自の記述なので、他のデータベースと共通で使えるPDOには正しく解釈されないためだと思います。 対応方法としては、パラメータをそれぞれ数値型として渡す必要があるようです。 あと、見たところ「-36」となっているので、$pageが設定されていないようです。 これは、他のコードですでに対応されているようですが、どこからか現在ページを取得する前提で仮の変数です。 とりあえず1を入れてください。 訂正箇所の前後のコードです。 ---- // 取得した記事データの表示 $one_page_count = 36; $page = 1; $start_row = ($page - 1) * $one_page_count; $sql = 'SELECT * FROM rss_feed ORDER BY date LIMIT ?,?'; $stmt = $dbh->prepare($sql); $stmt->bindParam(1, $start_row, PDO::PARAM_INT); $stmt->bindParam(2, $one_page_count, PDO::PARAM_INT); $stmt->execute(); while ($item = $stmt->fetch(PDO::FETCH_OBJ)) { ---- 総件数については、まったく考えていませんでした。 次のページがあるかないかを知るために必要でしたね。 当初の質問では記事とRSSを表示する内容だったため、ページングは記事側(WordPress)に任せるつもりでした。 記事とRSSの両方を表示する段になって、ページングをどちらの件数にそろえるかで、総件数の算出方法がかわってくると思います。 RSSが36件×10ページと言うのもあるので、最大ページが10と考えれば、総件数はあまり関係なくなるような気もします。 今は10ページ目以外(1ページ目~9ページ目)は「次ページ」のようなリンクで遷移するだけでよろしいかと思います。
お礼
$count = 54; // データの総数 $perPage = 36; // 1ページあたりのデータ件数 $totalPage = ceil($count / $perPage); // 最大ページ数 $page = (int) $_GET['page'];//現在のページ番号 上記のもので投稿ページの記事はカウントできますが、RSSは不可能だと思われるので、関数を自作して似たようなものを自作するしか方法はなさそうです。
補足
ということは元のページングの処理のものと複合させることで処理をより簡単に進められるのではないかということでしょうか? ページングは既に別にあるのですが RSSの下ではなく記事の下に設置しています RSS→記事の場所です
- dell_OK
- ベストアンサー率13% (766/5721)
補足 2022/01/23 15:50 10ページ分の読み込み速度が極端に下がることはないと思います。 と断言したいところですが、それはサーバーの性能によると思います。 これは試してみるしかありません。 ただ、実際の読み込みにはLIMITを指定して1ページ分ずつになるので心配ないと思います。
お礼
表示に関して難しい点がありまして、 画像とタイトルを表示するものとタイトルのみを表示するものでRSSを分けて並べて表示したいと思っております。 ここで1点難しい記述になるのではないかと危惧してることがあり、 カウントを取る時に1セットで計算できないのではないでしょうか…
補足
ありがとうございます。 ページの遷移について今考えているのですが、 自分が調べた記事では、下記のように書いてありました。 ページ制御をするには以下の情報が必要になります。 現在ページ 1ページあたりの表示件数 データの総件数 SELECT A.* FROM ( SELECT A.*, -- 行番号を取得 ROWNUM RNUM, -- 総件数を取得 COUNT(*) OVER () TOTAL_COUNT FROM ( -- この部分のSQLを書き換える SELECT A.COL1, A.COL2, A.COL3 FROM A ORDER BY COL1 ) A ) A WHERE 1=1 -- 現在ページに表示する範囲で取得 AND A.RNUM BETWEEN :R_FROM AND :R_TO ORDER BY A.RNUM 教えていただいたコードを使わせていただこうと思ったのですが、$stmt->execute([$start_row, $one_page_count]);でエラーが出ております。 調べてみたのですが、対応マニュアルを見てくださいと書いているのみで修正しきれませんでした… Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''-36','36'' at line 1 ※全体のコードになります。 <?php try { $dsn = 'mysql:dbname=hlxclitx_wp1;host=localhost'; $user = 'hlxclitx_wp1'; $password = 'E.HrypHWxNmltXgC5eS26'; $dbh = new PDO($dsn, $user, $password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //エラーが発生した時に、例外を投げる echo 'データベースへの接続が出来ました'; } catch (PDOException $e) { echo $e->getMessage(); // err時はメッセージを表示 exit; } //RSSをまとめる $url1 = [ 'http://blog.livedoor.jp/dqnplus/index.rdf', 'http://alfalfalfa.com/index.rdf', 'http://himasoku.com/index.rdf', ]; // insertの準備 $stmt = $dbh->prepare('insert into rss_feed (title, link, date) values (?, ?, ?) on duplicate key update title=?, link=?, date=?'); // URLのループ開始 テーブルに格納 foreach ($url1 as $url) { if (($rss = @simplexml_load_file($url)) === false) { continue; } foreach ($rss->item as $item) { $title = $item->title; $link = $item->link; $dc = $item->children('http://purl.org/dc/elements/1.1/'); $date = date('Y-m-d H:i:s', strtotime($dc->date)); $stmt->execute([$title, $link, $date, $title, $link, $date]); } } // 取得した記事データの表示 $one_page_count = 36; $start_row = ( $page - 1 ) * $one_page_count; $sql = 'SELECT * FROM rss_feed ORDER BY date LIMIT ?,?'; $stmt = $dbh->prepare($sql); $stmt->execute([$start_row, $one_page_count]); while ($item = $stmt->fetch(PDO::FETCH_OBJ)) { echo '<ul>'; printf('<li class="sitelink"><a href="%s">%s</a></li>', $item->link, $item->title); printf('<li class="sitelink"><a href="%s">site</a></li>', $item->link); printf('<li class="sitedate">%s</li>', $item->date); echo '</ul>'; } //古いデータを削除 $sql = 'DELETE FROM rss_feed WHERE date < ?'; $stmt = $dbh->prepare($sql); $date = date('Y-m-d H:i:s', strtotime('-1 week')); $stmt->execute([$date]); ?>
- dell_OK
- ベストアンサー率13% (766/5721)
「USING BTREE」についてはなぜ付いたのかわかりません。 最初はphpMyAdminの構造画面で「すべてチェックする」して「ユニーク」にしただけでした。 「CREATE TABLE ~」は、私が手で書いたものではなく、以下のようなSQLを実行すると得られるCREATE文です。 show create table rss_feed; phpMyAdminで実行すると文字列が長くて表示しきれていませんが、結果の上に「+オプション」があるので、そこから「全文」を選択すると表示されます。 この時点ではまだ「USING BTREE」は付いていませんでした。 ただ、構造画面のインデックスのところにはデータ型として「USING BTREE」が表示されています。 それから、気づいたのが自動で付いたユニークキーの名前の「title」。 私はこれが気に入らなかったので「編集」でユニークキーらしい名前の「UK」に変更しました。 そして改めてCREATE文を取得すると「USING BTREE」が付いていたのです。 構造画面で確認して付いていれば大丈夫だと思います。
お礼
今から表示数をカウントするのではなくプライマリーキーのついたデータから記事をカウントしてforeach break文で制限する方法を調べてみます。
補足
「USING BTREE」についてはなぜ付いたのかわかりません。 最初はphpMyAdminの構造画面で「すべてチェックする」して「ユニーク」にしただけでした。 A.データベースでインデックスを触ったところ、設定がありUSING BTREEにすることができました。 ありがとうございます。 ページングにつきましてはもう1つ方法を見つけたのですが、自分は先ほど見つけた2つの方法で実装を目指してみます。 COUNT/LIMIT法、ページ数対応 <?php $_get_page = $_GET["page"]; $_get_query = $_GET["q"]; $csql = "SELECT COUNT(*) as 'cnt' FROM table WHERE data=:q"; // 総件数カウント用SQL $ssql = "SELECT * FROM table WHERE data=:q LIMIT :start, 10 ORDER BY `id`"; // データ抽出用SQL $dbh = new PDO("mysql:localhost", "user", "pass"); // DB接続 // データ抽出用SQLを、プリペアドステートメントで実行 $ssth = $dbh->prepare($ssql); $ssth->bindValue(":q", $_get_query); $ssth->bindValue(":start", $_get_page * 10); $ssth->execute(); $data = $ssth->fetchAll(PDO::FETCH_ASSOC); // 総件数カウント用SQLを、プリペアドステートメントで実行 $csth = $dbh->prepare($csql); $csth->bindValue(":q", $_get_query); $csth->execute(); $total = $csth->fetchColumn(PDO::FETCH_ASSOC); $pages = ceil($total / 10); // 総件数÷1ページに表示する件数 を切り上げたものが総ページ数 ?> <html> <body> <ul> <?php foreach($data as $row) { printf("<li>%s</li>\n", $row["column"]); } ?> </ul> <?php for($i=0; $i < $pages; $i++) { printf("<a href='?page=%d&q=%s'>%dページへ</a><br />\n", $i, $_get_query, $i); } ?>
- dell_OK
- ベストアンサー率13% (766/5721)
はい、タイトルやサイトは問題なく表示されています。 タイトルと「site」はリンクになっていて、そのURLへジャンプできています。 ---- データベースへの接続が出来ました 【悲報】女子高生に流行ってる〇〇系男子、おっさんには理解不能 site 2022-01-23 04:17:17 【画像あり】ファッションデザイナーがキチゲを解放した結果wwwwwww site 2022-01-23 04:01:00 【速報】米津玄師さん、限界突破wwwwwwwwwwwwww site 2022-01-23 03:30:39
補足
$sql = 'SELECT title FROM rss_feed ORDER BY date';//テーブルを選択 $stmt = $dbh -> prepare($sql);//一回の関数コールの中で SQL ステートメントを準備して実行し、 結果を PDOStatement オブジェクトとして返します。 $count = $stmt -> rowCount();//SELECT 文によって返された行をカウントする echo $count.'件SELECTしました。';//テスト確認 $perPage = 36; // 1ページあたりのデータ件数 $totalPage = ceil($count / $perPage); // 最大ページ数 $page = (int) $_GET['page'];//現在のページ番号 上記のコードを考えたのですが、以下のテーブルが選択されません。記述は調べた通りなのですが… $sql = 'SELECT title FROM rss_feed ORDER BY date';//テーブルを選択 最大ページ数の仕組みに困っております。最大ページをコントロールできなかった場合、コンテンツが途中で途切れる可能性がありますが。 改善策はないでしょうか?
- dell_OK
- ベストアンサー率13% (766/5721)
私が勝手に決めた仕様でテストしているコードを挙げてみます。 コードエディタで整形しているので、質問者さまのコードとは少々変わっています。 勝手に決めた仕様 ・RSSの内容が変更されることはない、または、変更されたら別物として扱う(重複しているように見えるかも) ・取得したRSSが重複しているものは全項目ユニークキーで対処する ・古いデータは1週間で削除する テーブルの構造 試す場合は、いったんテーブルを削除してください。 ---- CREATE TABLE `rss_feed` ( `title` VARCHAR (256) NOT NULL, `link` VARCHAR (256) NOT NULL, `date` datetime NOT NULL, UNIQUE KEY `UK` (`title`, `link`, `date`) USING BTREE ) ---- PHPコード ---- <?php try { $dsn = 'mysql:dbname=hlxclitx_wp1;host=localhost'; $user = 'hlxclitx_wp1'; $password = 'E.HrypHWxNmltXgC5eS26'; $dbh = new PDO($dsn, $user, $password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //エラーが発生した時に、例外を投げる echo 'データベースへの接続が出来ました'; } catch (PDOException $e) { echo $e->getMessage(); // err時はメッセージを表示 exit; } //RSSをまとめる $url1 = [ 'http://blog.livedoor.jp/dqnplus/index.rdf', 'http://alfalfalfa.com/index.rdf', 'http://himasoku.com/index.rdf', ]; // insertの準備 $stmt = $dbh->prepare('insert into rss_feed (title, link, date) values (?, ?, ?) on duplicate key update title=?, link=?, date=?'); // URLのループ開始 テーブルに格納 foreach ($url1 as $url) { if (($rss = @simplexml_load_file($url)) === false) { continue; } foreach ($rss->item as $item) { $title = $item->title; $link = $item->link; $dc = $item->children('http://purl.org/dc/elements/1.1/'); $date = date('Y-m-d H:i:s', strtotime($dc->date)); $stmt->execute([$title, $link, $date, $title, $link, $date]); } } // 取得した記事データの表示 $sql = 'SELECT * FROM rss_feed ORDER BY date DESC'; $stmt = $dbh->prepare($sql); $stmt->execute(); while ($item = $stmt->fetch(PDO::FETCH_OBJ)) { echo '<ul>'; printf('<li class="sitelink"><a href="%s">%s</a></li>', $item->link, $item->title); printf('<li class="sitelink"><a href="%s">site</a></li>', $item->link); printf('<li class="sitedate">%s</li>', $item->date); echo '</ul>'; } //古いデータを削除 $sql = 'DELETE FROM rss_feed WHERE date < ?'; $stmt = $dbh->prepare($sql); $date = date('Y-m-d H:i:s', strtotime('-1 week')); $stmt->execute([$date]); ----
お礼
こちらもコードを試させていただいたところ成功いたしました。ありがとうございます。 昨日こちらから送信させていただいた通りデータが0,2022,0 で表示されたのは何が原因だったのか明確にわかりませんでしたが、助かりました。ありがとうございます。 VARCHARにしていないのが原因でしたかね… USING BTREEについてお聞きしたいのですが、手動でインデックスからUNIQUE KEY `UK`を設定した場合どうすればよいのでしょうか?
補足
1点だけお聞きしたいのですが、タイトルやリンク等は表示されておりますでしょうか? 0,2022,0と表示されているので疑問だったのですが…
- dell_OK
- ベストアンサー率13% (766/5721)
補足 2022/01/22 01:48 数についてですが、私が言った何件削除するかの事でしょうか。 データベースがパンクするほどになっているとは思わなかったので、説明を後回しにしていました。 360件保持する、のとは少し違いますが、私が考えていたのは、データベースがパンクしない程度で360件以上保持できる期間を決めて、それ以前のデータを削除する方法です。 なので、削除する件数を算出する必要はありませんでした。 例えば、1週間以前を削除するとしたらこんな感じです。 --- $sql = 'DELETE FROM rss_feed WHERE date < ?'; $stmt = $dbh->prepare($sql); $date = date('Y-m-d H:i:s', strtotime('-1 week')); $stmt->execute([$date]); ---- 実際にサイト数を増やしてどれくらいRSSがたまるかによって、その期間を調整することになると思います。
補足
RSSのcronと同じ法則で1週間で削除するのですね確かにその方法は思いつきませんでした。 これであれば問題なさそうです。 気になる点があるのですがRSSを15サイトから引っ張ってきて1日で削除するループで回した場合 10ページ分の読み込み速度が極端に下がることは考えられないでしょうか?
- dell_OK
- ベストアンサー率13% (766/5721)
syntax error, unexpected end of file このエラーは、今回の場合、どこかの } がないために発生しています。 正しい箇所に } を追加すればエラーは解消されますが、まだ、デザインを含めた表示に関しては、私は触れないようにしています。 データベースのものを読み込み一覧表示ができてからにしたいので、ひとまず、下記の部分は削除してください。 この foreach の { に対する } がないためにエラーになっています。 ーーーー // サイトごとに表示するなら、サイトタイトル表示はこの位置 printf('<h2>%s</h2>', $site_title); $count = 0; // 個別記事のループ開始 RSSの取得が始まる foreach ($rss->item as $item) { if (++$count > 8) break; $title = $item->title;//タイトル取得 $link = $item->link;//リンクを取得 $dc = $item->children('http://purl.org/dc/elements/1.1/');//RSSの情報を取得 $thumb = $item->thumb->url;//画像を取得 ーーーー
お礼
もう1点ご指摘を頂いたのですが、もしかすると原因はこれかもしれません。 例6 要素および属性をテキストと比較する 要素または属性を(中略)文字列を引数とする関数に渡すには(中略)文字列にキャストする必要があります。 $title = (string) $item->title;
補足
1番下の行に}を追加することで解消致しました。 ご指摘ありがとうございます。 var_dampで確認したところ$title$linkで0が返ってきてしまいます。 $stmtかsimplexml_load_fileが原因のようです。 try文で全体を囲ってみてエラー文の確認を行います
- dell_OK
- ベストアンサー率13% (766/5721)
実は、質問者さまはとても難しいことに臨んでいます。 私では及ばないようなところなので、解決まで私が歩めるかわかりませんが、できる限りのことはしたいと思っています。 重複については何をアドバイスしたらいいのかわかりませんでした。 その前に、私が気にしていることがあって、RSSの仕様を正確に把握しておく必要があります。 重要なのは、現在データベースに保存している項目である、タイトル、リンク、日付が変更されて再度RSS配信されることがあるのかないのかをはっきりさせることです。 変更されない場合を考えてみます。 どなたのコメントかわかりませんが言われているとおり、SELECTとINSERTの間に他者からのINSERTが入るかもしれないので、存在チェックをしているパート1では重複が発生します。 パート2のSQLでされてるようにユニークインデックスを追加して、'insert into ~ on duplicate key update ~'でINSERTすればいいと思います。 重複データがあった場合にUPDATEが実行されてしまうかも知れませんが、間髪入れずに実行されるので重複は回避できます。 「UPDATEが実行されてしまうかも」と言ったのは、もしすべてが同じ値であった場合、MySQLがUPDATEを実行しないかもしれないと思っているからです。 実際に更新時にタイムスタンプを更新する項目を追加して試してみましたが、この項目が更新されなかったのでUPDATEは実行されていない感じがします。 'on duplicate key update'を使わないとしても、ユニークインデックスがあればduplicate keyエラーが発生するので、実行結果をチェックしてこの場合は無視して処理を続行するかです。 パート2のSQLが成功したかどうかわかりませんが、「CREATEUNIQUEINDEX」はエラーになると思います。 単語の間にスペースが必要だと思います。 CREATE UNIQUE INDEX rss_feed(title,link,date); ちなみにこれは毎回実行するのではなくて、phpMyAdminなどで1回実行するだけです。 私の方ではこんな感じでした。 ALTER TABLE `rss_feed` ADD UNIQUE( `title`, `link`, `date`); 次に変更される場合を考えてみます。 取得済みのRSSの内容①が、②や③のように変更されると仮定します。 ① 【画像】ポケモン新作さん、サイズ感を忠実に再現した結果がこちら http://alfalfalfa.com/articles/318945.html 2022-01-22 16:10:00 ②タイトルとリンクと日付が変更されている 【画像】ポケモン新作さん、サイズ感を忠実に再現した結果 http://alfalfalfa.com/articles/318946.html 2022-01-22 16:15:00 ③タイトルと日付が変更されている 【画像】ポケモン新作さん、サイズ感を忠実に再現した結果 http://alfalfalfa.com/articles/318945.html 2022-01-22 16:15:00 もし②のように、変更されることがあるとしたらどうすることもできません。 パート1のSQLでも、パート2のSQLでも、タイトルとリンクと日付のすべてが同じものがあるかで判定されるからです。 これは重複ではないと考えるしかありません。 言いかえると、この重複はしてもいいことにする、です。 もし③のように、変更されるとしてもタイトルか日付だけでリンクは変更されないのであればリンクを主キーかユニークインデックスにすることで重複を回避できます。 これはあくまで一番変わりそうにないのがリンクかなと私が思っているのでリンクにしていますが、タイトルが変わらないのであればタイトルで、日付が変わらないのであれば日付でその役目にできます。 なにか変わらない項目がひとつあり、かつ、それがそのサイトまたは全世界で唯一のものであればその役目にできます。 このRSSのXMLの<content:encoded>~</content:encoded>を見てみましたが、複雑なので解読をあきらめました。 もしかしたらこの中に不変かつ唯一のなにかがあるような気がするので、それがわかれば②のような変更があっても重複を回避できそうです。 ただ、サイトによってこの内容が違うかも知れませんので、そうなるとそれぞれに対応する必要が出てきます。
お礼
実は、質問者さまはとても難しいことに臨んでいます。 私では及ばないようなところなので、解決まで私が歩めるかわかりませんが、できる限りのことはしたいと思っています。 A.ありがとうございます。 RSSの仕様を正確に把握しておく必要があります。 重要なのは、現在データベースに保存している項目である、タイトル、リンク、日付が変更されて再度RSS配信されることがあるのかないのかをはっきりさせることです。 A.もう1度確認をとってみます。 「UPDATEが実行されてしまうかも」と言ったのは、もしすべてが同じ値であった場合、MySQLがUPDATEを実行しないかもしれないと思っているからです。 実際に更新時にタイムスタンプを更新する項目を追加して試してみましたが、この項目が更新されなかったのでUPDATEは実行されていない感じがします。 A.値はキャッシュがない限りはテーブルに残っているようです。 このRSSのXMLの<content:encoded>~</content:encoded>を見てみましたが、複雑なので解読をあきらめました。 もしかしたらこの中に不変かつ唯一のなにかがあるような気がするので、それがわかれば②のような変更があっても重複を回避できそうです。 ただ、サイトによってこの内容が違うかも知れませんので、そうなるとそれぞれに対応する必要が出てきます。 A.御手数かけましてすみません。主キーかユニークインデックスを設定して避けるよう考えてみます。
補足
すみません。以下の構文で保存しようとしたんですがエラーが起きます。 syntax error, unexpected end of file end ifやendwhileを入れてみたのですが解消できません。 思い当たる箇所はありますでしょうか? <?php try { $dsn = 'mysql:dbname=hlxclitx_wp1;host=localhost'; $user = 'hlxclitx_wp1'; $password = 'E.HrypHWxNmltXgC5eS26'; $dbh = new PDO($dsn,$user,$password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);//エラーが発生した時に、例外を投げる echo "データベースへの接続が出来ました"; }catch (PDOException $e) { echo $e->getMessage();// err時はメッセージを表示 exit; } //RSSをまとめる $url1 = [ 'http://blog.livedoor.jp/dqnplus/index.rdf', 'http://alfalfalfa.com/index.rdf', 'http://himasoku.com/index.rdf',]; // insertの準備 $stmt = $dbh->prepare('insert into rss_feed (title, link, date) values (?, ?, ?)'); // URLのループ開始 テーブルに格納 foreach ($url1 as $url) { if (($rss = @simplexml_load_file($url)) === false) { continue; } foreach ($rss->item as $item) { $title = $item->title; $link = $item->link; $dc = $item->children('http://purl.org/dc/elements/1.1/'); $date = date('Y-m-d H:i:s', strtotime($dc->date)); $stmt->execute([$title, $link, $date]); } } // サイトごとに表示するなら、サイトタイトル表示はこの位置 printf('<h2>%s</h2>', $site_title); $count = 0; // 個別記事のループ開始 RSSの取得が始まる foreach ($rss->item as $item) { if (++$count > 8) break; $title = $item->title;//タイトル取得 $link = $item->link;//リンクを取得 $dc = $item->children('http://purl.org/dc/elements/1.1/');//RSSの情報を取得 $thumb = $item->thumb->url;//画像を取得 // 取得した記事データの表示 $sql = 'SELECT * FROM teblename ORDER BY date DESC'; $stmt = $dbh->prepare($sql); $stmt->execute(); while ($item = $stmt->fetch(PDO::FETCH_OBJ)) { print('<ul>'); printf('<li class="sitelink"><a href="%s">%s</a></li>', $item->link, $item->title); printf('<li class="sitelink"><a href="%s">site</a></li>', $item->link); printf('<li class="sitedate">%s</li>', $item->date); print('</ul>'); } ?>
- dell_OK
- ベストアンサー率13% (766/5721)
回答No.9さま、ありがとうございます。 おかげさまで私も少し気になっていたことを知ることができました。 テスト環境と実働環境が同じにできないのはつらいところのようです。 質問者さまへ。 データベース登録処理と表示処理の分割は元のご質問に回答しました。 エンコードやデコードは必要なさそうな気がします。
お礼
先ほどはすみません。}を1つ抜かしておりました。 表示してみたところ、以下のように表示されデータの取得に失敗しているようなので、原因を調べてみます。 site 2022 0 site 2022 0 site 2022 … etc
補足
回答の場所がなくこちらに書かせていただきます。 それぞれコードを調べたのですが、難しく修正するのに時間がかかっています。 アドバイスいただけると助かります。 1.重複について //重複insertを回避するようにしていたとしてもプログラムの実行やデータベースへの書き込みなどで処理時間がかかっている間に重複insertしてしまうのが原因でしょう。 ※パート1, SELECT 'title,link,date' FROM rss_feed WHERE (title,link,date) in = (SELECT (title,link,date) FROM items); //INSERTする前に、INSERTしようとしているキー項目で、テーブルにSELECTしてデータが存在するかどうかチェックします。 パート2, CREATEUNIQUEINDEX rss_feed(title,link,date); 2.数について AUTO_INCREMENTをチェックしてcheck制約をコマンドプロンプトで作成すればいいのはわかるんですが、phpで制限することはできないでしょうか? プライマリーキーを使って制限する方法もあるのですが、コミットする方法しか書いてないためどのように組むのかわかりません。 ※SELECT max(id) FROM foo;でプライマリーキーを設定したカラムの数を取得できるようですが、これにつなげて数を制限する方法について考えています。 last_insert_rowid()を使ってもカラム数を取得できるようですがidを取得して、その後カラム数を取得する必要がありそうで2段階必要だと思われます。
- dell_OK
- ベストアンサー率13% (766/5721)
別の質問を見てクラスとリンクはできていると思えましたので、私からの回答は控えます。
お礼
$stmtは値を取得できないようです。以前別の方にもお聞きしたのですがほかの関数で代用するしかなさそうです。
補足
データベースに登録する処理と、表示する処理を分けたいのですが難しくてわかりません。アドバイスいただけないでしょうか? <?php try { $dsn = 'mysql:dbname=hlxclitx_wp1;host=localhost'; $user = 'hlxclitx_wp1'; $password = 'E.HrypHWxNmltXgC5eS26'; $dbh = new PDO($dsn,$user,$password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);//エラーが発生した時に、例外を投げる echo "データベースへの接続が出来ました"; }catch (PDOException $e) { echo $e->getMessage();// err時はメッセージを表示 exit; } //RSSをまとめる $url1 = [ 'http://blog.livedoor.jp/dqnplus/index.rdf', 'http://alfalfalfa.com/index.rdf', 'http://himasoku.com/index.rdf',]; // insertの準備 $stmt = $dbh->prepare('insert into rss_feed (title, link, date) values (?, ?, ?)'); //SQL文の中に変動値が入る場合、以下のようにPHPの変数を直接連結してしまうと「SQLインジェクション攻撃」により悪意のあるSQLが実行されてしまう可能性があります。 $sql->execute([$title, $link, $date]);//DB用のエスケープ処理をPDOに丸投げしたいから 格納したtitle, link, dateをエンコードしてdbに保存して、デコードして表示する流れになると思うのですが。 foreach ($不明->不明 as $不明) foreach文で囲う場合、title, link, dateをまとめた変数はどのような形になるのでしょうか?
お礼
期間をけてからの質問で申し訳ないのですが、コードを整理中に修正が必要な個所があり原因がわかりません echo "<li class=\"sitedate\">{$item->date}</li>"; で画像やカテゴリーなどは表示できるのでしょうか? 個別に指定して表示する必要があるのでしょうか? 1.投稿に画像やカテゴリーなどが表示されず、タイトルと日付けのみ表示されている 2.RSS画像にURLがついておらず画像のみ表示されている ※該当箇所 if (!empty($item->img)) { echo "<li><img src=\"{$item->img}\" width=\"100\"></li>"; } 3.RSSの画像がない場合ダミー画像を表示させたいが書き方が調べてもわからない
補足
ありがとうございます。 引き続きコードを組んでみます…