简体   繁体   中英

How can I make categories for all the posts?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM