Php mvc: Redirection issue on form submission

Hi everyone

I have started playing around with php mvc custom framework. So far I am able to submit and display content, etc. But I am running into issues redirecting to a specific page after new post submission. Any help would be greatly appreciated. Here is my code:
PostsModel

public function save() {
        try {           
            $sql = ("INSERT INTO posts (uid, title, body) 
            VALUES (:uid, :title, :body");
            $db = static::getDB();
            $stmt = $db->prepare($sql);
            $stmt->bindParam(':uid', $_REQUEST['uid'], PDO::PARAM_STR);
            $stmt->bindParam(':title', $_REQUEST['title'], PDO::PARAM_STR);
            $stmt->bindParam(':body', $_REQUEST['body'], PDO::PARAM_STR);
        
            return $stmt->execute();
        
         }catch(PDOException $e) {
            echo $e->getMessage();
         }
         return true;
     }

PostsController

/**
  * Show new post form
  */
  public function newAction() {
      View::renderTemplate('services/posts/new.html');
  }
  /**
  * Create the post
  */
  public function createAction() {
    $blog = new PostsModel($_POST);
        if ($blog->save()) {
            $this->redirect('/posts/success');
        } else {
            View::renderTemplate('services/posts/new.html', [
                'post' => $post
            ]);
        }
  }
  /**
  * Show the submission success page
  */
    public function successAction()
    {   
        View::renderTemplate('services/posts/success.html');
    }

View - form

<form action="createPost" id="newPost" method="POST">
            {{ current_user.fName }} 
            <input type="hidden" placeholder="uid" name="uid" value="{{ current_user.id }}">
            <input type="text" placeholder="Title" name="title" value="{{ post.title }}">
            <textarea name="body" id="body" cols="30" rows="10"></textarea>
            <button type="submit">Create Post</button> 
        </form>
<form action="createPost" id="newPost" method="POST">
            {{ current_user.fName }} 
            <input type="hidden" placeholder="uid" name="uid" value="{{ current_user.id }}">
            <input type="text" placeholder="Title" name="title" value="{{ blog.title }}">
            <textarea name="body" id="body" cols="30" rows="10"></textarea>
            <button type="submit">Create</button> 
        </form>

That tells us nothing. What EXACTLY are the “issues”?

Like already stated you need to tell us exactly what the problem is; however, in my opinion you’re making you classes to specific in my opinion. While the following is base on the Active Record Design pattern this probably can be rework into MVC or give a good idea on to go about doing it.

You should pull the users data into an array (doing it the HTML Form is the easiest way) then set that to a class. Here’s an example of what I’m talking about :slight_smile:

class CMS extends DatabaseObject
{
    protected static string $table = "cms"; // Table Name:
    static protected array $db_columns = ['id', 'user_id', 'thumb_path', 'image_path', 'Model', 'ExposureTime', 'Aperture', 'ISO', 'FocalLength', 'author', 'heading', 'content', 'data_updated', 'date_added'];
    public $id;
    public $user_id;
    public $page;
    public $thumb_path;
    public $image_path;
    public $Model;
    public $ExposureTime;
    public $Aperture;
    public $ISO;
    public $FocalLength;
    public $author;
    public $heading;
    public $content;
    public $date_updated;
    public $date_added;

    /*
     * Create a short description of content and place a link button that I call 'more' at the end of the
     * shorten content.
     */
    #[Pure] public static function intro($content = "", $count = 100): string
    {
        return substr($content, 0, $count) . "...";
    }

    public function setImagePath($image_path) {
        $this->image_path = $image_path;

    }

    public static function styleTime($prettyDate): string
    {
        try {
            $dateStylized = new DateTime($prettyDate, new DateTimeZone("America/Detroit"));
        } catch (Exception $e) {
        }

        return $dateStylized->format("Y-m-d H:i:s");
    }

    public static function countAllPage($page)
    {
        static::$searchItem = 'page';
        static::$searchValue = $page;
        $sql = "SELECT count(id) FROM " . static::$table . " WHERE page=:page";
        $stmt = Database::pdo()->prepare($sql);

        $stmt->execute([ static::$searchItem => static::$searchValue ]);
        return $stmt->fetchColumn();

    }

    protected static function filterwords($text){
        $filterWords = array('Edited for Obvious Reasons');
        $filterCount = sizeof($filterWords);
        for ($i = 0; $i < $filterCount; $i++) {
            $text = preg_replace_callback('/\b' . $filterWords[$i] . '\b/i', function($matches){return str_repeat('*', strlen($matches[0]));}, $text);
        }
        return $text;
    }

    /*
     * Put the date from 00-00-0000 00:00:00 that is stored in the MySQL
     * database table to a more presentable format such as January 1, 2021.
     */
    public static function styleDate($prettyDate): string
    {

        try {
            $dateStylized = new DateTime($prettyDate, new DateTimeZone("America/Detroit"));
        } catch (Exception $e) {
        }

        return $dateStylized->format("F j, Y");
    }

    /*
     * Construct the data for the CMS
     */
    public function __construct($args = [])
    {
//        $this->user_id = $args['user_id'] ?? null;
//        $this->author = $args['author'] ?? null;
//        $this->heading = $args['heading'] ?? null;
//        $this->content = $args['content'] ?? null;
//        $this->date_updated = $args['date_updated'] ?? null;
//        $this->date_added = $args['date_added'] ?? null;


        // Caution: allows private/protected properties to be set
        foreach ($args as $k => $v) {
            if (property_exists($this, $k)) {
                $v = static::filterwords($v);
                $this->$k = $v;
                static::$params[$k] = $v;
                static::$objects[] = $v;
            }
        }
    } // End of construct method:

} // End of class:

Here’s the HTML form that I used:

    <form id="formData" class="form_classes" action="edit.php" method="post" enctype="multipart/form-data">
        <input type="hidden" name="cms[id]" value="<?= $id ?>">
        <input type="hidden" name="cms[user_id]" value="<?= $_SESSION['id'] ?>">
        <input type="hidden" name="cms[author]" value="<?= Login::full_name() ?>">
        <input type="hidden" name="cms[date_updated]" value="<?= $date_updated ?>">
        <input type="hidden" name="action" value="upload">
        <input type="hidden" name="cms[image_path_name]" value="<?= $cms->image_path ?>">
        <img src="<?= "../" . $_SESSION['old_image'] ?>" alt="current image">
        <br>
        <div class="file-style">
            <input id="file" class="file-input-style" type="file" name="image" value="<?= $cms->image_path ?>">
            <label for="file">Select file</label>
        </div>
        <div class="heading-style">
            <label class="heading_label_style" for="heading">Heading</label>
            <input class="enter_input_style" id="heading" type="text" name="cms[heading]" value="<?= $cms->heading ?>"
                   tabindex="1" required autofocus>
        </div>
        <div class="content-style">
            <label class="text_label_style" for="content">Content</label>
            <textarea class="text_input_style" id="content" name="cms[content]"
                      tabindex="2"><?= $cms->content ?></textarea>
        </div>
        <div class="submit-button">
            <button class="form-button" type="submit" name="submit" value="enter">submit</button>
            <button class="form-button" formaction="delete.php?id=<?= $id ?>"
                    onclick="return confirm('Are you sure you want to delete this item?');">Delete
            </button>
        </div>
    </form>

That way you simple can do the following in a class (I’ll use the update method as it’s a little shorter):

Example:


    /*
     * This is the update that method that I came up with and
     * it does use named place holders. I have always found
     * updating is easier than creating/adding a record for
     * some strange reason?
     */
    public function update(): bool
    {
        /* Initialize an array */
        $attribute_pairs = [];

        /* Create the prepared statement string */
        foreach (static::$params as $key => $value)
        {
            if($key === 'id') { continue; } // Don't include the id:
            $attribute_pairs[] = "{$key}=:{$key}"; // Assign it to an array:
        }

        /*
         * The sql implodes the prepared statement array in the proper format
         * and updates the correct record by id.
         */
        $sql  = 'UPDATE ' . static::$table . ' SET ';
        $sql .= implode(", ", $attribute_pairs) . ' WHERE id =:id';

        /* Normally in two lines, but you can daisy chain pdo method calls */
        Database::pdo()->prepare($sql)->execute(static::$params);

        return true;

    }

Like I said it’s not coded of MVC, but the Active Record Design pattern, but it should be easy to modify it to MVC or at least get a good idea. The whole GitHub repository can be found here → https://github.com/Strider64/phototechguru

Sponsor our Newsletter | Privacy Policy | Terms of Service