简体   繁体   中英

Prepared Statement in PHP MVC

I am trying to create a simple forum in a MVC architecture.
This is my database setup (the relevant part):

Table: forum_categories

`forum_categories` (
`cat_id` INT(8) NOT NULL AUTO_INCREMENT,
`cat_title` VARCHAR(255) NOT NULL,
`cat_desc` TEXT NOT NULL,
PRIMARY KEY (`cat_id`),
UNIQUE KEY (`cat_title`)

Table: forum_topics

`forum_topics` (
`topic_id` INT(8) NOT NULL AUTO_INCREMENT,
`cat_id` INT(8) NOT NULL COMMENT 'foreign key with forum_categories table',
`user_id` INT(11) NOT NULL COMMENT 'foreign key with users table',
`topic_title` VARCHAR(255) NOT NULL,
`topic_desc` TEXT NOT NULL, 
`topic_date` DATETIME DEFAULT NULL,
PRIMARY KEY (`topic_id`),
FOREIGN KEY (`cat_id`) REFERENCES forum_categories (`cat_id`) ON DELETE CASCADE ON UPDATE CASCADE

Example of the functionality, I would like to achieve:
Category 1 has cat_id = 1
Category 2 has cat_id = 2

Topic 1 has cat_id = 1
Topic 2 has cat_id = 2

Now when category 1 is selected I just want topic 1 to show.
If category2 is selected I just want topic 2 to show.

This prepared SQL statement achieves that:

PREPARE stmnt FROM 
    'SELECT * 
    FROM forum_categories fc
    JOIN forum_topics ft ON fc.cat_id = ft.cat_id
    WHERE fc.cat_id = ?
    ORDER BY ft.topic_date DESC';

SET @a = 1;
EXECUTE stmnt USING @a;


My Problem : I would like to move this functionality into my PHP MVC structure.
Here is my attempt, which does not work (it shows all topics in all categories).

Controller

/**
* Show all the topics in the chosen category
*/
public function showForumTopics()
{
    $topic_model = $this->loadModel('Forum');
    $this->view->forum_topics = $topic_model->getForumTopics();
    $this->view->render('forum/viewTopics');
}

Model

/**
* Gets an array that contains all the forum topics in the database.
* Each array element is an object, containing a specific topic's data.
* @return array All the forum topics
*/
public function getForumTopics($cat_id)
{
     $sql = 'SELECT * FROM forum_categories fc JOIN forum_topics ft ON fc.cat_id = ft.cat_id WHERE fc.cat_id = :cat_id ORDER BY ft.topic_date DESC';
     $query = $this->db->prepare($sql);
     $query->execute(array(':cat_id' => $cat_id));

     return $query->fetchAll();
}

View

if ($this->forum_topics) {
            foreach($this->forum_topics as $key => $value) {
                echo '<p><strong>Title:</strong>' . $value->topic_title . '</p>';
                echo '<p><strong>Description:</strong> ' . $value->topic_desc . '</p>';
                echo '<p><strong>Author:</strong> ' . $value->topic_author . '</p>';
                echo '<p><strong>Date:</strong> ' . $value->topic_date . '</p>';
            }
        } else {
            echo 'No forum topics.';
        }

Help would be highly appreciated! Thank you!!

For example, your page http://example.com/?cat_id=2 Your code should be like this

Controller

public function showForumTopics()
{
    $default_category = 1;
    $topic_model = $this->loadModel('Forum');
    $cat_id = isset($_GET['cat_id']) ? $_GET['cat_id'] : $default_category;
    $this->view->forum_topics = $topic_model->getForumTopics($cat_id);
    $this->view->render('forum/viewTopics');
}

Model

public function getForumTopics($cat_id) {
     $sql = 'SELECT * FROM forum_categories fc JOIN forum_topics ft ON fc.cat_id = ft.cat_id WHERE fc.cat_id = :cat_id ORDER BY ft.topic_date DESC';
     $query = $this->db->prepare($sql);
     $query->execute(array(':cat_id' => $cat_id));

     return $query->fetchAll(); }

View

if ($this->forum_topics) {
            foreach($this->forum_topics as $key => $value) {
                echo '<p><strong>Title:</strong>' . $value->topic_title . '</p>';
                echo '<p><strong>Description:</strong> ' . $value->topic_desc . '</p>';
                echo '<p><strong>Author:</strong> ' . $value->topic_author . '</p>';
                echo '<p><strong>Date:</strong> ' . $value->topic_date . '</p>';
            }
        } else {
            echo 'No forum topics.';
        }

Your problem is that your backend requires and ID to pull the specific category (and via the join, the correct topic). In your DB Query, you are looking for it here: WHERE fc.cat_id = ?

Your getForumTopics($cat_id) function also requires the ID to pass into that prepared statement. Problem is you aren't passing any ID into that function when you call it:

$this->view->forum_topics = $topic_model->getForumTopics();

So without anything coming through, your function is now broken and should be throwing an error. You have two options at this point:

  1. Provide an ID from the page, through the controller to your function (hint, you'll have to add it to the URL like @kringeltorte suggested so the page knows what to load!)
  2. Make a backup that lists all topics when no specific category is chosen. You'd do that with something like this in your function definition:

     // Specifying the backup option null here, for when there is no ID passed public function getForumTopics($cat_id = null) { // Simple check for an ID if ($id) { // Run the code you had before $sql = 'SELECT * FROM forum_categories fc JOIN forum_topics ft ON fc.cat_id = ft.cat_id WHERE fc.cat_id = :cat_id ORDER BY ft.topic_date DESC'; $query = $this->db->prepare($sql); $query->execute(array(':cat_id' => $cat_id)); return $query->fetchAll(); } } else { // Otherwise, do the same thing as above but without a WHERE clause } } 

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