I am trying to learn and understand PHP and MySQL. I decided to make a small project and learn as I progress.
Now I have my DB something like this (ill try to keep it clean without all fields):
users
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL,
articles
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
body TEXT NOT NULL
To display all articles I used PHP PDO
$sql = 'SELECT * FROM articles';
$query = $db->prepare($query);
$query->execute();
$articles = $query->fetchAll();
And to display single article I created new article.php page and went with this
$id = $_GET['id'];
$sql = 'SELECT * FROM articles WHERE id = :id';
$query = $db->prepare($sql);
$query->execute(['id' => $id]);
$article = $query->fetch();
And id is from index page something like this
<a href="<?php echo ROOT_URL ?>article.php?id=<?php echo $article['id'];?>Read Post</a>
Far as it goes by now everything works fine but my first question is how can I make categories for all the post. I had in mind making a new table and altering articles table by adding FOREIGN KEY:
articles
FOREGEIN KEY (cat_id) REFERENCES categories(id)
ON DELETE CASCADE ON UPDATE CASCADE
categories
id INT NOT NULL AUTO INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
But now I don't know exectly how to make query to get all articles with same category similar to article.php where it would be category.php instead.
And my second question is what query should I use to enable users to leave comments on article. I have idea how table needs to look
comments
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
body varchar(255) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE ON UPDATE CASCADE
FOREIGN KEY (post_id) REFERENCES posts(id)
ON DELETE CASCADE ON UPDATE CASCADE
And I wrote something like this
if (isset($_POST['comment'])) {
$body = $_POST['body'];
$article_id = $_POST['article_id'];
$user_id = $_SESSION['id'];
$sql = "INSERT INTO comments(user_id, article_id, body) VALUES (:user_id, :article_id, :body)";
$query = $db->prepare($sql);
$query->execute(['user_id' => $user_id, 'article_id' => $article_id, 'body' => $body]);
}
<input type="hidden" name="article_id" value="<?php echo $article['id'] ?>">
<button type="submit" name="comment">Leave a Comment</button>
But comments went on all of the articles.
If you want to select all articles, which one is in some category. You can do something like this.
$id = $_GET['category_id'];
$sql = 'SELECT * FROM articles WHERE cat_id = :id';
$query = $db->prepare($sql);
$query->execute(['id' => $id]);
foreach($query->fetchAll() as $results){
// Here you can make a magic.
echo '<h2>' . $results['Article_Name'] . '</h2>';
print_r($results);
}
The same principle you can do with comments. Just to make a query on every article page.
Like this one for example.
SELECT * FROM comments WHERE article_id = :article_id
how to make query to get all articles with same category similair to article.php where it would be category.php instead
It's literally the same thing, just the names change:
SELECT *
FROM articles
WHERE cat_id = :cat_id
However, I think sooner or later you'll need to join tables, which is the core feature of relational databases (sadly, there're many developers who think that SELECT * FROM tablename
is all the SQL you'll every need). In this case, you can do something like this:
SELECT cat.id AS cat_id, cat.name AS cat_name, art.id AS art_id, art.body
FROM categories cat
INNER JOIN articles art ON cat.id = art.cat_id
WHERE cat.id = :cat_id
ORDER BY art.id DESC
There's a classic article that explains this pretty nicely: A Visual Explanation of SQL Joins
what query should I use to enable users to leave comments on article
You don't really way where you're stuck but it's basically the same story (same query, different names):
SELECT *
FROM comments
WHERE post_id = :post_id
Finally, two random tips:
I would not set ON DELETE CASCADE
for articles.cat_id
. I don't see much real life usage for batch removing articles by category and it makes easy to do it by mistake.
Try to make your naming consistent. You only have 4 entities and you're already using different terms for the same stuff (category vs cat, article vs post).
Mysql tables example:
CREATE TABLE IF NOT EXISTS `articles` (
`id` bigint(22) NOT NULL AUTO_INCREMENT,
`userid` bigint(22) NOT NULL DEFAULT 0,
`catid` bigint(22) NOT NULL DEFAULT 0,
`title` varchar(190) NOT NULL DEFAULT '',
`text` text,
`active` int(1) NOT NULL DEFAULT 1,
`ban` int(3) NOT NULL DEFAULT 0,
`ip` varchar(200) NOT NULL DEFAULT '',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `ukey` (`userid`,`title`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `categories` (
`id` bigint(22) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`slug` varchar(50) NOT NULL,
`active` int(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `ukey` (`slug`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
// Add first category (after this id = 1 for example)
INSERT INTO categories(name,slug) VALUES('Category 1', 'cat1-slug')
// Here userid == logged user id
// Here: catid == id field from categories table (category id from categories table)
INSERT INTO articles(userid,catid,title,text) VALUES(1,1,'Article title','Article content')
Select articles with category name (mysql join)
SELECT articles.*,categories.name,categories.slug,categories.id as catid from articles LEFT JOIN categories ON articles.catid = categories.id WHERE articles.active = 1 AND articles.catid = 1
Don't use it, it's not needed:
FOREGEIN KEY (cat_id) REFERENCES categories(id)
ON DELETE CASCADE ON UPDATE CASCADE
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.