• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:RSSをデータベースに格納できない)

RSSをデータベースに格納できない

このQ&Aのポイント
  • 昨日教えていただいたコードで格納して表示するところまで成功しました。自分の不注意でデータベースネームと違う、新規作成したテーブルに格納していたため起こったエラーでした。申し訳ありません。
  • 再度全体のコードと組み合わせてみたのですがエラーが起こり困っております。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(); ?>

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

  • ベストアンサー
  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.70

お礼 2022/02/09 18:47 ・cronを同じサイトで複数実装してもエラーにはならないでしょうか? WordPressのCronを試してみました。 CronスケジュールひとつにCronイベントを複数登録できました。 エラーにはならいようです。

php_learn
質問者

お礼

期間をけてからの質問で申し訳ないのですが、コードを整理中に修正が必要な個所があり原因がわかりません 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の画像がない場合ダミー画像を表示させたいが書き方が調べてもわからない

php_learn
質問者

補足

ありがとうございます。 引き続きコードを組んでみます…

その他の回答 (69)

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.69

補足 2022/02/11 12:51 自作関数と言うか、以下の③のところです。 ①と②で③を求めます。 ④がRSSの開始番目ですが、現在のページ番号から求めています。 *④と*③でそれぞれを使って読み込んでいます。 ①$block_per_page = 2; //ページあたりブロック件数 ②$rss_per_block = 18; //ブロックあたりRSS件数 $posts_per_block = $wp_query->post_count / $block_per_page; //ブロックあたり投稿件数 //RSS読み込み ③$rss_per_page = $block_per_page * $rss_per_block; //ページあたりRSS件数 ④$rss_offset = ($current_page - 1) * $rss_per_page; //RSSオフセット $sql = 'SELECT * FROM rss_feed ORDER BY date DESC LIMIT ?,?'; $stmt = $dbh->prepare($sql); *④$stmt->bindParam(1, $rss_offset, PDO::PARAM_INT); *③$stmt->bindParam(2, $rss_per_page, PDO::PARAM_INT);

php_learn
質問者

お礼

調べてみたのですが、わからない点があるので教えていただけると助かります。 //表示 for ($i = 0; $i < $block_per_page; ++$i) {//変数の初期化;ページあたりの投稿数がページあたりブロック件数より小さい間は繰り返す;for文の中の命令を一度実行するたびにiが一増える echo '<h2>ブロック</h2>'; echo '<h3>RSS</h3>'; for ($j = 0; $j < $rss_per_block; ++$j) {//13件まで繰り返す 変数の初期化;ページあたりのRSS数がブロックあたりRSS件数より小さい間は繰り返す;for文の中の命令を一度実行するたびにjが一増える $item_index = $i * $rss_per_block + $j;//1ページのアイテム数=ページあたりの投稿数×ブロックあたりRSS件数+ページあたりのRSS数 if ($item_index >= count($rss_items)) {//もし1ページのアイテム数が$rss_itemとは何か?より大きいならカウントをやめる break; } $item = $rss_items[$item_index];//アイテム=$rss_itemとは何か?(1ページのアイテム数) echo '<ul>'; echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>"; echo "<li class=\"sitelink\"><a href=\"{$item->link}\">site</a></li>"; echo "<li class=\"sitedate\">{$item->date}</li>"; if (empty($item->img)) { $img = 'wp-content/uploads/2021/12/EXt1cESWAAAwdOY.jpg'; } else { $img = $item->img; } echo "<li><a href=\"{$item->link}\"><img src=\"{$img}\" width=\"100\"></a></li>"; echo '</ul>'; } わからないところ ページあたりブロック件数は2件しかない状態でページあたりの投稿数となぜ比較するのかわかりません。 $rss_itemとは何でしょうか? RSSをタイトル、タイトル画像、タイトル画像に分ける場合 ifで分岐すればよいのでしょうか? //表示 for ($i = 0; $i < $block_per_page; ++$i) {//投稿よりもページあたりブロック件数のほうが多い echo '<h2>ブロック</h2>'; echo '<h3>RSS</h3>'; for ($j = 0; $j <= 14; $j < $rss_per_block; ++$j) {//ページあたりのRSS数よりもブロックあたりRSS件数のほうが多い $item_index = $i * $rss_per_block + $j;//投稿のアイテム数=ページあたりの投稿数×ページあたりのブロック件数 if ($item_index >= count($rss_items)) {//もし投稿のアイテム数が大きいならRSSアイテムをカウントするのをやめる break; } //ここからRSS3ブロック $item = $rss_items[$item_index]; if ($j = 0; $j < 6; $i++) { echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>"; } if ($j = 6; $j < 10; $i++) { echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>";//タイトルのみ for ($j = 0; $i < 4; $j < $rss_per_block; ++$j) {//ページあたりのRSS数よりもブロックあたりRSS件数のほうが多い echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>"; echo "<li class=\"sitelink\"><a href=\"{$item->link}\">site</a></li>"; echo "<li class=\"sitedate\">{$item->date}</li>"; if (empty($item->img)) {//もし画像が空の場合 $img = 'wp-content/uploads/2021/12/EXt1cESWAAAwdOY.jpg'; } else { $img = $item->img;//画像を取得する } echo "<li><a href=\"{$item->link}\"><img src=\"{$img}\" width=\"100\"></a></li>"; if ($j = 10; $j < 14; $i++) { echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>"; echo "<li class=\"sitelink\"><a href=\"{$item->link}\">site</a></li>"; echo "<li class=\"sitedate\">{$item->date}</li>"; if (empty($item->img)) {//もし画像が空の場合 $img = 'wp-content/uploads/2021/12/EXt1cESWAAAwdOY.jpg'; } else { $img = $item->img;//画像を取得する } echo "<li><a href=\"{$item->link}\"><img src=\"{$img}\" width=\"100\"></a></li>"; echo '</ul>'; }

php_learn
質問者

補足

自作関数と言うか、以下の③のところです。 ①と②で③を求めます。 ④がRSSの開始番目ですが、現在のページ番号から求めています。 *④と*③でそれぞれを使って読み込んでいます。 ①$block_per_page = 2; //ページあたりブロック件数 ②$rss_per_block = 18; //ブロックあたりRSS件数 $posts_per_block = $wp_query->post_count / $block_per_page; //ブロックあたり投稿件数 //RSS読み込み ③$rss_per_page = $block_per_page * $rss_per_block; //ページあたりRSS件数 ④$rss_offset = ($current_page - 1) * $rss_per_page; //RSSオフセット $sql = 'SELECT * FROM rss_feed ORDER BY date DESC LIMIT ?,?'; $stmt = $dbh->prepare($sql); *④$stmt->bindParam(1, $rss_offset, PDO::PARAM_INT); *③$stmt->bindParam(2, $rss_per_page, PDO::PARAM_INT); A.解説いただきありがとうございます。$block_per_page * $rss_per_block;でページあたりのRSSということですが、phpでも計算できるんですね。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.68

「A.無視した場合、表示にの件数についての影響はないのでしょうか? 初期は合わせた数字を1ページとしたように認識していたのですが…」 影響はないので安心してください。 初期から合わせたものと思われていたのは、私の説明不足でした。 最初から投稿件数でページを考えていたので問題ないと思います。 RSSはRSS用のページあたり件数があるので、何番目から何番目までを表示するかを、投稿のページに基づいて算出しています。

php_learn
質問者

お礼

コードを間違えておりました。タイトル、タイトル画像、タイトル画像を出力するコードを組んでみたのですがどうでしょうか? //表示 for ($i = 0; $i < $block_per_page; ++$i) {//投稿よりもページあたりブロック件数のほうが多い echo '<h2>ブロック</h2>'; echo '<h3>RSS</h3>'; for ($j = 0; $j <= 14; $j < $rss_per_block; ++$j) {//ページあたりのRSS数よりもブロックあたりRSS件数のほうが多い $item_index = $i * $rss_per_block + $j;//投稿のアイテム数=ページあたりの投稿数×ページあたりのブロック件数 if ($item_index >= count($rss_items)) {//もし投稿のアイテム数が大きいならRSSアイテムをカウントするのをやめる break; } //ここからRSS3ブロック $item = $rss_items[$item_index]; if ($j = 0; $j < 6; $i++) { echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>"; } if ($j = 6; $j < 10; $i++) { echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>";//タイトルのみ if ($j = 10; $j < 14; $i++) { echo "<li class=\"sitelink\"><a href=\"{$item->link}\">{$item->title}</a></li>"; echo "<li class=\"sitelink\"><a href=\"{$item->link}\">site</a></li>"; echo "<li class=\"sitedate\">{$item->date}</li>"; if (empty($item->img)) {//もし画像が空の場合 $img = 'wp-content/uploads/2021/12/EXt1cESWAAAwdOY.jpg'; } else { $img = $item->img;//画像を取得する } echo "<li><a href=\"{$item->link}\"><img src=\"{$img}\" width=\"100\"></a></li>"; echo '</ul>'; }

php_learn
質問者

補足

影響はないので安心してください。 初期から合わせたものと思われていたのは、私の説明不足でした。 最初から投稿件数でページを考えていたので問題ないと思います。 A.ご説明ありがとうございます。 RSSはRSS用のページあたり件数があるので、何番目から何番目までを表示するかを、投稿のページに基づいて算出しています。 A.ページあたり件数というのは自作関数で制限しているということでしょうか?

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.67

お礼 2022/02/10 14:37 最終ページについてはこんな風にするのはどうでしょうか。 表示設定の「1ページに表示する最大投稿数」も活かしてみたいと思います。 表示設定の「1ページに表示する最大投稿数」は「$wp_query->post_count」で取得できそうです。 これに基づいて最大ページも「$wp_query->max_num_pages」で取得できました。 「1ページに表示する最大投稿数」の言葉通り1ページの投稿数なので、ブロックあたり投稿件数はページあたりブロック件数で割って求めます。 ページングは投稿件数にしか対応していないので、RSSの件数は無視していいと思います。 ---- //ページ番号チェック if (ctype_digit($_REQUEST['page'])) { $current_page = (int) $_REQUEST['page']; //現在ページ } else { $current_page = 1; //先頭ページ } //最大ページチェック if ($current_page > $wp_query->max_num_pages) { $current_page = $wp_query->max_num_pages; } $block_per_page = 2; //ページあたりブロック件数 $rss_per_block = 18; //ブロックあたりRSS件数 $posts_per_block = $wp_query->post_count / $block_per_page; //ブロックあたり投稿件数 ----

php_learn
質問者

補足

最終ページについてはこんな風にするのはどうでしょうか。 表示設定の「1ページに表示する最大投稿数」も活かしてみたいと思います。 A.最大数をwordpressで取得するんですね、$iで計算する方法を考えておりました。 「1ページに表示する最大投稿数」の言葉通り1ページの投稿数なので、ブロックあたり投稿件数はページあたりブロック件数で割って求めます。 ページングは投稿件数にしか対応していないので、RSSの件数は無視していいと思います。 A.無視した場合、表示にの件数についての影響はないのでしょうか? 初期は合わせた数字を1ページとしたように認識していたのですが… 下記のコードを使用させていただいたところ正常に動作いたしました。ありがとうございます。 ---- //ページ番号チェック if (ctype_digit($_REQUEST['page'])) { $current_page = (int) $_REQUEST['page']; //現在ページ } else { $current_page = 1; //先頭ページ } //最大ページチェック if ($current_page > $wp_query->max_num_pages) { $current_page = $wp_query->max_num_pages; } $block_per_page = 2; //ページあたりブロック件数 $rss_per_block = 18; //ブロックあたりRSS件数 $posts_per_block = $wp_query->post_count / $block_per_page; //ブロックあたり投稿件数

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.66

全体でチェックするので foreach の部分はなくしてください。

php_learn
質問者

補足

了解いたしました。自分でもコードを組んでみます。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.65

お礼 2022/02/10 14:02 ・値に文字が含まれている場合は1ページ目にするという方法がよくわかりません。 この部分を、 ---- $current_page = $_REQUEST['page'] ?? 1; //現在ページ ---- こんな風にしてみてください。 ---- //ページ番号チェック if (ctype_digit($_REQUEST['page'])) { $current_page = (int) $_REQUEST['page']; //現在ページ } else { $current_page = 1; //先頭ページ } ----

php_learn
質問者

補足

現在のページが数字でないなら1に戻るという構文なのですね… 勉強になりました。考え方がまだ固いようで、思いつかなかったです…

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.64

WP Crontrolをインストールしてみました。 Windowsでも動くようなので、Linuxのcronとは違うもののようですね。 どういう仕組みかわかりませんが、それなりに対応できると思います。 私が勉強しないといけないこともあるので、回答がこれまでよりも遅くなりますかも知れませんのでご了承ください。 ただ、本質問と今後のWP Crontrolに関する質問の内容が乖離するようであれば、他の人からの回答をいただいた方がいいと思いますので、その際には別の質問を立てるようにしていただければと思います。 一連の流れであればこのままで。

php_learn
質問者

補足

私が勉強しないといけないこともあるので、回答がこれまでよりも遅くなりますかも知れませんのでご了承ください。 A.ありがとうございます。 ただ、本質問と今後のWP Crontrolに関する質問の内容が乖離するようであれば、他の人からの回答をいただいた方がいいと思いますので、その際には別の質問を立てるようにしていただければと思います。 A.了解いたしました。引き続きよろしくお願いいたします。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.63

お礼 2022/02/09 18:47 WordPressからcronの設定ができるのですね。 てっきり直接サーバーに設定するのかと思っていました。 詳しくないのでわかりませんが、いろいろなサイクルで実装したいことは想定されていると思いますので、複数設定する方法が正式にあると思います。 いずれにしても、cronで実行するようになった場合、RSS取得とデータベース保存および古いRSS削除はindex.phpからなくなるので、だいぶすっきりしそうですね。

php_learn
質問者

お礼

値に文字が含まれている場合は1ページ目にするという方法がよくわかりません。 $current_page = $_REQUEST['page'] ?? 1; //現在ページ foreach ($current_page as $text) {//数字と数字以外 if (ctype_digit($text) === false) {//数字以外ならfalse数字ならcontinue continue; } } $block_per_page = 2; //ページあたりブロック件数 $rss_per_block = 18; //ブロックあたりRSS件数 $posts_per_block = 5; //ブロックあたり投稿件数

php_learn
質問者

補足

WP Crontrolというプラグインでコントロールしております。 ここからはプラグイン前提の話になりますので、導入していただくことは可能でしょうか?

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.62

補足 2022/02/09 18:38 ctype_digit関数がいいと思います。 $_REQUEST['page']は文字列なので、int型の心配はありません。

php_learn
質問者

お礼

最終ページについてRSSと投稿数を足して計算する方法がわからないのですが… $iを使って無理やり計算する方法もあると思うのですが、 表示設定で計算する場合表示の際の記述と共通する部分をコードで書く必要がありそうなので、迷っております。 ※RSSと投稿の記事を足して×2したもの = count($total); //1ページの記事数 $maxPage = ceil($total / $?);//表示できる最大ページ数を 件数 / 1ページに表示するリソース数 で求めます。

php_learn
質問者

補足

了解いたしました。コードを考えてみます。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.61

(1) 不正な値が入力されないか ユーザーが操作できるのはURLくらいだと私も思います。 今のところ、$_REQUEST($_POST、$_GET)で取得しているのは'page'だけです。 URLに「?page=a」のように文字を入れるとエラーになりました。 なので、ここをどうにかする必要はありそうです。 例えば、私が思いつく確認としては以下の2つです。 ①値に文字("0"~"9"ではないもの)が含まれている場合、1ページ目にする ②値が最終ページより大きい場合、最終ページにする 入力フォームがないので、値の確認は$_REQUEST['page']をphpで受け取ったあとになります。 (2) 他所に迷惑をかけていないか 言われるようにcronで実行するのがいいと思います。 サイクルをどれくらいにするかは私には決められませんので、質問者さまに決めていただくとして、考え方としては。 1日おき0時に実行すると、閲覧できるのは前日分までとなります。 当日分が閲覧できないため、それでもいいかどうかですね。 指摘では、閲覧タイミングで実行されることから、「秒単位で大量に何度もアクセスしたりしないか」だと思われます。 私はcronで1時間おき00分でもいいような気はします。 1時間おきが頻繁かどうかはわからないため、それぞれのRSSサイトに確認するのが確実でしょうけれども、そこまでしなくても、って感じがします。 (3) DBに接続できないとき正しくエラーはハンドリングできているか だだもれにならないようにするためのtry~catchです。 だだもれになりそうなのがエラーメッセージの表示なので、ここはなくしましょう。 echo $e->getMessage(); // err時はメッセージを表示 「exit;」だけにすると、何も表示されない画面になります。 エラーメッセージのかわりに「メンテナンス中」などを表示するようにしてみてください。 それ用のページを用意して飛ばす方法もありますが、URLが変わらない方がいいような気もするので、ひとまずそれはやめておきましょう。 「メンテナンス中」の表示処理は、functions.phpに定義してください。 例えばこんな感じです。 ---- if (!function_exists('display_maintenance')) { function display_maintenance() { echo <<<maintenance <hr> ただいまメンテナンス中です。<br> しばらく時間をおいてアクセスしてください。 <hr> maintenance; } } ---- echo <<<maintenance と maintenance; の間は普通にHTMLの記述です。 変動的なものを表示したいようでしたら含めることもできます。 「php ヒアドキュメント」などで検索するとヒントが得られると思います。 この「maintenance」はそれっぽいものにしましたが、開始と終了が同じであればなんでもいいです。 他の表示方法でももちろんかまいません。 私が楽をしたくてちょっとこの方法で書いてみました。 それで、エラーの場合にこれを呼ぶようにします。 connect_dbの定義のところです。 } catch (PDOException $e) { display_maintenance(); exit; }

php_learn
質問者

お礼

15日ごとにランキングを出力するものを以前組んだことがあるのですがとんでもない量のコードになっております。 cronを同じサイトで複数実装してもエラーにはならないでしょうか? // 15日毎にアクセスをリセットして人気記事を表示 //アクセス数をカウントする function set_post_views() { $postID = get_the_ID(); $num = (int)date_i18n('H'); // 現在時間で番号取得 $key = 'pv_count'; $count_key = '_pv_count'; $count_array = get_post_meta($postID, $count_key, true); $sum_count = get_post_meta($postID, $key, true); if (!is_array($count_array)) { //配列ではない $count_array = array(); $count_array[$num] = 1; } else { //配列である if (isset($count_array[$num])) { //カウント配列[n]が存在する $count_array[$num] += 1; } else { //カウント配列[n]が存在しない $count_array[$num] = 1; } } //アクセス数を更新する update_post_meta($postID, $count_key, $count_array); update_post_meta($postID, $key, $sum_count + 1); } //アクセス数をリセットする function reset_post_views() { $num = (int)date_i18n('H'); $key = 'pv_count'; $reset_key = '_pv_count'; $args = array( 'posts_per_page' => -1, 'post_type' => 'post', 'post_status' => 'publish', 'meta_key' => $reset_key, ); $reset_posts = get_posts($args); if ($reset_posts) : foreach ($reset_posts as $reset_post) : $postID = $reset_post->ID; $count_array = get_post_meta($postID, $reset_key, true); if (isset($count_array[$num])) { //カウント配列[n]が存在する $count_array[$num] = 0; } //アクセス数をリセットする update_post_meta($postID, $reset_key, $count_array); update_post_meta($postID, $key, array_sum($count_array)); endforeach; endif; } //リセット関数を実行するアクションフックを追加 add_action('set_hours_event', 'reset_post_views'); //実行間隔の追加 function my_interval($schedules) { // 1時間ごとを追加 $schedules['1hours'] = array( 'interval' => 3600, 'display' => 'every 1 hours' ); return $schedules; } add_filter('cron_schedules', 'my_interval'); //アクションフックを定期的に実行するスケジュールイベントの追加 function my_activation() { if (!wp_next_scheduled('set_hours_event')) { wp_schedule_event(1451574000, '1hours', 'set_hours_event'); } } add_action('wp', 'my_activation'); //ボットの判別 function isBot() { $bot_list = array( 'Googlebot', 'Yahoo! Slurp', 'Mediapartners-Google', 'msnbot', 'bingbot', 'MJ12bot', 'Ezooms', 'pirst; MSIE 8.0;', 'Google Web Preview', 'ia_archiver', 'Sogou web spider', 'Googlebot-Mobile', 'AhrefsBot', 'YandexBot', 'Purebot', 'Baiduspider', 'UnwindFetchor', 'TweetmemeBot', 'MetaURI', 'PaperLiBot', 'Showyoubot', 'JS-Kit', 'PostRank', 'Crowsnest', 'PycURL', 'bitlybot', 'Hatena', 'facebookexternalhit', 'NINJA bot', 'YahooCacheSystem', 'NHN Corp.', 'Steeler', 'DoCoMo', ); $is_bot = false; foreach ($bot_list as $bot) { if (stripos($_SERVER['HTTP_USER_AGENT'], $bot) !== false) { $is_bot = true; break; } } return $is_bot; } add_action('manage_posts_custom_column', function ($column_name, $post_id) { //データベース情報をグローバル変数として取得 global $wpdb; //タイムゾーンを設定 date_default_timezone_set('Asia/Tokyo'); if ($column_name == 'view') { //トータルアクセス数を表示 echo '<p>' . wpp_get_views($post_id, 'all', false) . '</p>'; //日別アクセス数を表示 for ($i = 0; $i >= -6; $i--) { $wpdb->get_results("SELECT id FROM wp_popularpostssummary WHERE postid = $post_id and view_date = '" . date('Y-m-d', strtotime($i . ' day')) . "'"); echo $wpdb->num_rows; if ($i != -6) { echo '|'; } } } }, 10, 2); remove_filter('the_content', 'wptexturize'); remove_filter('the_excerpt', 'wptexturize'); remove_filter('the_title', 'wptexturize');

php_learn
質問者

補足

例えば、私が思いつく確認としては以下の2つです。 ①値に文字("0"~"9"ではないもの)が含まれている場合、1ページ目にする ②値が最終ページより大きい場合、最終ページにする A.数値以外のものを調べる関数はいろいろあるようですが、どれが良いのでしょうか? 1.is_numeric関数 数字または数値形式の文字列か調べます。 文字列型でも小数点でも数値ならOK!(true)判定してくれます。 2.is_int関数 整数(int)型か調べてくれます。 数値でも文字列型だとダメ!(false)判定なので、厳しいです。 3.preg_match関数 正規表現で自由に数値チェックできます。 4.ctype_digit関数 文字列が数字かどうか調べてくれます。 文字列を判定する関数で、整数int型だとfalse判定になるこることもあるため、文字列のみを指定するようにしましょう。 (2) 他所に迷惑をかけていないか 私はcronで1時間おき00分でもいいような気はします。 1時間おきが頻繁かどうかはわからないため、それぞれのRSSサイトに確認するのが確実でしょうけれども、そこまでしなくても、って感じがします。 A.1時間はかなり頻繁な気がします。通常は3時間おき程度だと思われますので、2~3時間での実装が好ましいですかね。 (3) DBに接続できないとき正しくエラーはハンドリングできているか だだもれにならないようにするためのtry~catchです。 echo <<<maintenance と maintenance; の間は普通にHTMLの記述です。 変動的なものを表示したいようでしたら含めることもできます。 「php ヒアドキュメント」などで検索するとヒントが得られると思います。 この「maintenance」はそれっぽいものにしましたが、開始と終了が同じであればなんでもいいです。 A.参考にさせていただきました。ありがとうございます。 エラーの時に把握できれば良いので問題ないかと思われます。

  • dell_OK
  • ベストアンサー率13% (766/5720)
回答No.60

index.phpのurl1のURLはなくしてください。 functions.phpの$stmtもなくしてください。 function get_rss_site_url() { return [ 'http://nns2ch.net/index.rdf', 'http://aqua2ch.net/index.rdf', 'https://worldfn.net/index.rdf', ]; } $stmtを使い回しする場合はあります。 たいていの場合は、その都度違うSQLを準備する②、実行する③ので大丈夫です。 重複ということにはならないように組めば問題ありません。 今はひとつのSQLをループの中で何度も実行するのでループより前に準備しています。 私はそのような方法を知らなかったので、ループの中で毎回準備するような方法で作っていました。 SQLの変更がない限り1回でいいようなので、これは私の勉強になりました。 もしふたつ以上のSQLをループの中で実行する場合は、ループの中で毎回$stmtを準備するか、重複しないようにするため、ループの外で$stmt1、$stmt2のように必要な分の準備をしておいて、$stmt1->execute()、$stmt2->execute()と実行すれば大丈夫です。

php_learn
質問者

お礼

セキュリティについてご指摘があったものについてアドバイスをいただきたいのですが、それぞれわからない点があります。 (1) 不正な値が入力されないか  →表示設定で「$current_page = $_REQUEST['page'] ?? 1; //現在ページ」とありますが、このリクエストに数値以外が入力されても問題ないか  →それ以外に外部から入力された値($_REQUESTや$_POST、$_GETなどで取得できる値)は適切に不正な値が混入されないようにできているか A.現在のページはページ番号をクリックしたときに自動でコンテンツが切り替わるものなのでユーザーが操作できるものなのか? ※ユーザーが変えられるとしたらURLくらい? →それ以外に外部から入力された値($_REQUESTや$_POST、$_GETなどで取得できる値)は適切に不正な値が混入されないようにできているか A.ユーザーが入力するフォームがないので値をバリデーションで確認するような場所は存在するのか? (2) 他所に迷惑をかけていないか  →他所からRSSを取得するタイミングは適切か。秒単位で大量に何度もアクセスしたりしないか A.取得するタイミングの制限を設けたほうがいいのか、cronで1日おきなど? (3) DBに接続できないとき正しくエラーはハンドリングできているか  →PDOに接続できない場合に、処理を中断できるように出来ているか。画面上にエラーメッセージだだもれになったりしないか A.運用中のエラーを隠す理由=DB情報などが入る場合があるためと調べて発見したのですが、調べても方法が出てこないため困っております。 function connect_db() { 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 'データベースへの接続が出来ました'; return $dbh; //※接続したオブジェクトを返す } catch (PDOException $e) { echo $e->getMessage(); // err時はメッセージを表示 exit; } }

php_learn
質問者

補足

SQLの変更がない限り1回でいいようなので、これは私の勉強になりました。 もしふたつ以上のSQLをループの中で実行する場合は、ループの中で毎回$stmtを準備するか、重複しないようにするため、ループの外で$stmt1、$stmt2のように必要な分の準備をしておいて、$stmt1->execute()、$stmt2->execute()と実行すれば大丈夫です。 A.解説ありがとうございます。returnという便利な使いまわしできるオプションを使うことで実行をまとめることができるのですね これから指摘がありました、セキュリティ問題について取り掛かりたいのですが、このほかに追加すべきセキュリティなどがありましたら、教えていただけると助かります。 (1) 不正な値が入力されないか  →表示設定で「$current_page = $_REQUEST['page'] ?? 1; //現在ページ」とありますが、このリクエストに数値以外が入力されても問題ないか  →それ以外に外部から入力された値($_REQUESTや$_POST、$_GETなどで取得できる値)は適切に不正な値が混入されないようにできているか (2) 他所に迷惑をかけていないか  →他所からRSSを取得するタイミングは適切か。秒単位で大量に何度もアクセスしたりしないか (3) DBに接続できないとき正しくエラーはハンドリングできているか  →PDOに接続できない場合に、処理を中断できるように出来ているか。画面上にエラーメッセージだだもれになったりしないか

関連するQ&A