質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

1176閲覧

ページングを実装したい

haru-

総合スコア19

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2020/05/11 19:57

前提・実現したいこと

(例)PHPでtodoリストを作っています。
todoリストの内容は5件だけ表示したいです。

そこで表示までは上手くいったので、確認としてURLにindex.php?page=2などの数字を入れて
上手く表示しているか確認したところエラーが発生していました。

発生している問題・エラーメッセージ

Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'todo' cannot be null in /Applications/MAMP/htdocs/TODO/index.php on line 20
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'todo' cannot be null in /Applications/MAMP/htdocs/TODO/index.php on line 20

該当のソースコード

php

1<?php 2require('db.php'); 3 4 5if(!empty($_REQUEST)) { 6 // remove 7 if(isset($_REQUEST['id'])) { 8 $remove = $db->prepare('DELETE FROM todos WHERE id=?'); 9 $remove->execute(array( 10 $_REQUEST['id'] 11 )); 12 13 header('location:index.php'); 14 exit(); 15 } 16 17 //add 18 $add = $db->prepare('INSERT INTO todos SET todo=?, created_at=NOW()'); 19 $add->execute(array( 20 $_POST['todo'] 21 )); 22 header('location:index.php'); 23 exit(); 24} 25 26 27 28 // page todo 29 $todos = $db->prepare('SELECT * FROM todos ORDER BY id LIMIT ?, 5'); 30 31 32 33 34 $page = $_REQUEST['page']; 35 $todos->bindParam(1, $page, PDO::PARAM_INT); 36 $todos->execute(); 37 38 39 40 41 42 43?> 44 45<!DOCTYPE html> 46<html lang="ja"> 47<head> 48 <meta charset="UTF-8"> 49 <link rel="stylesheet" href="css/normalize.css"> 50 <link rel="stylesheet" href="css/style.css"> 51 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 52 53 <title>ToDo List</title> 54</head> 55<body> 56 <div id="container"> 57 <header> 58 <h1>ToDo List</h1> 59 </header> 60 <div class="add"> 61 <form action="" method="POST"> 62 <input type="text" required placeholder="Add plan!!" name="todo"> 63 <input type="submit" value="Add"> 64 </form> 65 </div> 66 <div class="todos"> 67 <form action="" method="POST"> 68 <?php while($todo = $todos->fetch()): ?> 69 <div class="todo"> 70 <div class="lavel"><div class="circle"></div></div> 71 <input type="checkbox" name="check" onclick="document.querySelector('p').classList.toggle('check')"> 72 <a href="todo.php?id=<?php print($todo['id']); ?>"><p><?php print(mb_substr($todo['todo'], 0 , 23)); ?><br><?php print($todo['created_at']); ?></p></a> 73 <div class="remove"> 74 <a href="index.php?id=<?php print $todo['id']; ?>" class="remove_btn">×</a> 75 <input type="button" value="Edit" name="edit" onClick="location.href='edit.php?id=<?php print($todo['id']); ?>'"> 76 </div> 77 </div> 78 <?php endwhile; ?> 79 </form> 80 <div class="page"> 81 82 <a href="index.php?page="><span>次のページ</span></a> 83 | 84 <a href=""><span>前のページ</span></a> 85 </div> 86 </div> 87 </div> 88 89</body> 90</html>

試したこと

todoの内容がnullにはできないと言っているのは分かるのですが、どこを直せば良いのか分かりません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

$_REQUESTはGETでもPOSTでもemptyにはならないので、必ず下記が実行されます。

php

1 $add = $db->prepare('INSERT INTO todos SET todo=?, created_at=NOW()'); 2 $add->execute(array( 3 $_POST['todo'] 4 )); 5 header('location:index.php'); 6 exit();

$_POSTなのかどうか、その中に値が指定されているかどうかも確認せずにそのまま突っ込むのは悪手です。
GETとPOSTで処理は明確に分けるべきです。

ただ、状況的に前の質問からほとんど進んでいません。

私が回答で「REQUEST METHOD」という絶対的なキーワードを提示しています。
そこから調べましょう。

あと、デバッグしましょう。
どこを通っているか、どこで止まったか、あらゆる場所(できれば分岐)に下記を入れれば分かります。

PHP

1echo __LINE__.PHP_EOL;

投稿2020/05/11 20:03

編集2020/05/11 20:05
m.ts10806

総合スコア80875

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

haru-

2020/05/11 20:23

すみません。全然進歩していなかったです…。 GETとPOSTで処理は明確に分けたところ上手く表示されました! ありがとうございます! echo __LINE__.PHP_EOL; というのを入れてみたのですが、その行数が表示されるだけなのですが 使い方はこれで良いのでしょうか? 調べたところ __LINE__ ファイル上の現在の行番号。 とリファレンスにも書いてあったので何もエラーがなければ、行数が表示されるということですか?
m.ts10806

2020/05/11 20:28

回答に書いた通り「どこを通っているか、どこで止まったか」を確認するためのものです。 意図しているところを通っているか、意図しないところを通っていないか、を確認します。 今回は意図しないところを通っているはずです。 それに、、、 header('location:index.php'); ↑これ、要らなくないですか? index.phpは提示されたコードですよね。わざわざリダイレクトさせる必要ないと思います。安易なリダイレクトはバグの元です。 あと、特にDBに変更をあたえる処理の時はトランザクションを張って、コミットorロールバックする仕組みは必ず入れましょう。 https://www.php.net/manual/ja/pdo.transactions.php 意図しない変更を防ぐため、DBで起きたエラーを拾うためです。
haru-

2020/05/11 20:47

header('location:index.php');がないと再読み込みした時に、再び同じ内容がDBに送られてしまいます…。 ありがとうございます! トランザクション調べて勉強してみます。
m.ts10806

2020/05/11 20:51

>再び同じ内容がDBに送られてしまいます…。 ん?それはどうしてでしょうか。 GET,POST明確に分けてキーのチェックまでしたのでしたら、「送られる」ことはなく、最新の情報をSELECTするだけに思いますが。
haru-

2020/05/11 21:08

``` if(!empty($_POST)) { // remove if(isset($_REQUEST['id'])) { $remove = $db->prepare('DELETE FROM todos WHERE id=?'); $remove->execute(array( $_REQUEST['id'] )); } //add $add = $db->prepare('INSERT INTO todos SET todo=?, created_at=NOW()'); $add->execute(array( $_POST['todo'] )); header('location:index.php'); exit(); } // page todo $todos = $db->prepare('SELECT * FROM todos ORDER BY id LIMIT ?, 5'); if(isset($_GET['page']) && is_numeric($_GET['page'])) { $page = $_GET['page']; } else { $page = 1; } $start = 5 * ($page - 1); $todos->bindParam(1, $start, PDO::PARAM_INT); $todos->execute(); ``` このように書いたのですが合っていますか?
m.ts10806

2020/05/11 21:11

実行してみたら分かると思いますが、前のコードに戻ってませんかね。。。 前の質問で私が 「一つずつ整合性を考えてコードを読んでいくと見えてくると思います。」 とアドバイスしていますが、実際にそのようにコードを読みましたか? プログラムは書いた通りにしか動かないので、感覚で組んでも想定の結果にはなりません。
haru-

2020/05/11 21:27

戻ってました。。。 header('location:index.php');が要らないというのは // removeの中のものでよかったですか? このようにしてみました。 if(!empty($_REQUEST)) { // remove if(isset($_REQUEST['id'])) { $remove = $db->prepare('DELETE FROM todos WHERE id=?'); $remove->execute(array( $_REQUEST['id'] )); } } //add if(!empty($_POST)) { $add = $db->prepare('INSERT INTO todos SET todo=?, created_at=NOW()'); $add->execute(array( $_POST['todo'] )); header('location:index.php'); exit(); }
m.ts10806

2020/05/11 21:31

自分のコードの説明を1行1行全てできますか? 「header('location:index.php');は不要」なのにまだ入ってますけど。 まだずっと感覚だけで書いてるように見受けられます。 そして、REQUEST METHODについても言及されないままです。
haru-

2020/05/11 21:57

「header('location:index.php');は不要」というのは // remove内のことかと思っていました。 REQUEST METHODについてはこういうことですよね。 if(!empty($_GET)) { if(isset($_GET['id'])) { $remove = $db->prepare('DELETE FROM todos WHERE id=?'); $remove->execute(array( $_GET['id'] )); } } 何度も同じことを質問してしまい申し訳ありません。 //addの中の方はやはりheader('location:index.php');がないと リロード時再度DBに送られてしまいます。 これから学校に行くので帰宅後、もう一度挑戦してみます。 そして自分のコードの全て説明できるようもう少し学習を進めてみます。 ご丁寧にありがとうございました。
kai0310

2020/05/11 22:08

> REQUEST METHODについてはこういうことですよね。 > if(!empty($_GET)) { > if(isset($_GET['id'])) { > $remove = $db->prepare('DELETE FROM todos WHERE id=?'); > $remove->execute(array( > $_GET['id'] > )); > } > } 横からすいません。質問をざっと見ただけなのですが、この様なことでは? if ($_SERVER['REQUEST_METHOD']=="POST") { // 処理... }
m.ts10806

2020/05/11 22:30

コードを書くのはきちんと考えをまとめてからにしましょう。 「PHP REQUEST METHOD」で調べればその手の説明の記事は幾らでも出てきます。 なるべくPHPマニュアルを確認してほしいですね。 https://www.php.net/manual/ja/reserved.variables.server.php (PHPマニュアル活用できない人はずっと初心者のままです)
haru-

2020/05/11 22:33

あ!全てにおいて勘違いしていました! REQUEST METHODは$_REQUESTのことだと勝手に決め付けていました。。。 $_SERVERというものがあるのですね! わざわざありがとうございました!!
kai0310

2020/05/11 22:34

まずは調べてみましょう。
m.ts10806

2020/05/11 22:57

プログラムは書いた通りに動きます。 思った通りには動きません。思い込みや決めつけは実装に出ますよ。 書いてあることが全てです。仕様が全てです。 調べた上でその調べた内容が正しいかどうか質問・確認すればトラブルなく済む話です。 (ただしコードを書いたなら動かさず「これでいいか?」聴くのはナンセンス。書いた通りにしか動かないから、動かせば結果が出る。結果によって対策を練る、調べる、やってみる この繰り返し)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問