0

I'm pretty new to php and jQuery. I've searched the net hi and low for an answer to no avail. I'm attempting to "post" an edit form that submits to itself using ajax and php. I'm able to return the values back to my form from the ajax.php. I'm also able to see them once they've posted, but the UPDATE query doesn't seem to be working. I'm not using ajax for anything other than getting values from a select. Something is hairy somewhere and I can't quite figure out where. I'm not too sure about my code either, but what I have seems to work up to/around the update query. Any help is much appreciated.

Here's my html, ajax call is at the bottom:

<?php //require_once("_includes/session.php"); ?>
<?php require_once("_includes/connection.php"); ?>
<?php require_once("_includes/functions.php"); ?>
<?php //confirm_logged_in(); ?>
<?php include("_includes/header.php"); ?>
<?php
if(isset($_POST['submit'])) {
    //$id = $_POST['postid'];
    //$title = $_POST['title'];
    //$content = $_POST['content'];
    //printf($id);
    //printf($title);
    //printf($content);
    $errors = array();

    // Form Validation
    $required_fields = array('title', 'content');
    foreach($required_fields as $fieldname) {
        if (!isset($_POST[$fieldname]) || (empty($_POST[$fieldname]) && !is_numeric($_POST[$fieldname]))) {
            $errors[] = $fieldname;
        }
    }

    $fields_with_lengths = array('title' => 50);
    foreach($fields_with_lengths as $fieldname => $maxlength ) {
        if (strlen(trim(mysql_prep($_POST[$fieldname]))) > $maxlength) { $errors[] = $fieldname; }
    }

    if (empty($errors)) {
        // Perform Update
        $id = mysql_prep($_POST['postid']);
        $title = mysql_prep($_POST['title']); 
        $content = mysql_prep($_POST['content']);

        $query = "UPDATE posts SET
                    title = '{$title}',
                    content = '{$content}',
                WHERE id = {$id}";
        $result = mysqli_query($connection, $query);
        if (mysqli_affected_rows($connection) == 1) {
            // Success
            $message = "The post was successfully updated.";
        } else {
            // Failed
            $message = "The subject update failed.";
            $message .= "<br>" . mysqli_error($connection);
        }

    } else {
        // Errors occurred
        if (count($errors) == 1) {
            $message = "There was " . count($errors) . " error in the form.";
        } else {
            $message = "There were " . count($errors) . " errors in the form.";
        }
    }

} // End: if(isset($_POST['submit']))
?>

<section id="manageContent">
<a href="manage.php">&lt&lt Back</a>

<h2>Edit Blog Post</h2>

<form id="newPost" name="newpost" action="edit_post.php" method="post">

<label for="posttitle">Select post title to edit:</label>

<select id="titleName" name="titleName">
    <?php
    $post_set = get_all_posts();
    while ($post = mysqli_fetch_array($post_set)) {
        echo '<option value="' . htmlspecialchars($post['id']) . '">'
            . htmlspecialchars($post['title'])
            . "</option>";
    }
    ?>
</select>

<p><label for="id">id:</label> <input id="postid" name="postid" type="text"></p>

<p><label for="title">Title:</label> <input id="title" name="title" type="text" required> (max length: 50 characters)</p>

<p><b>IMPORTANT!! things to remember so content is displayed how you would like:</b></p>
<ul>
    <li>You can use &ltp&gt, &ltdiv&gt, &ltul&gt, &ltol&gt, &ltli&gt tags in your blog posts.</li>
    <li>Insert the <b>&ltjumpbreak&gt</b> tag where you would like content to stop displaying on the main blog page.</li>
    <li>Enclose all remaining content after the <b>&ltjumpbreak&gt</b> in a <b>&ltdiv class="hideAfterJumpBreak"&gt&lt/div&gt</b> tag pair. This will keep all content after the <b>&ltjumpbreak&gt</b> from displaying on the main blog page until the topic is displayed on the topic.php page.</li>
    <li>Double check that every opening tag has a closing tag.</li>
</ul>

<p><label for="content">Content:</label></p>

<p><textarea id="content" name="content"></textarea></p>

<!--<p><button type="submit" name="submit">Edit Post</button></p> -->
<input id="submit" type="submit" name="submit" value="Edit Post">

<a href="edit_post.php"><button name="cancel">Cancel</button></a>
<a href="delete_post.php"><button name="delete">Delete</button></a>
</form>

<script>
(function() {

$("select#titleName").prop("selectedIndex", -1);

// returns a single item from php
/*
$("select#title").on("change", function() {
    var post_id = this.value;
    console.log(this);
    $.ajax ({
        url: "_includes/ajax.php",
        type: "POST",
        data: {post_id : post_id},
        dataType: "text",
        success: function(response) {
            $( "input#title" ).val(response);
        },
        failure: function() {
            alert("fail");
        }
    }); 
});
*/

$("select#titleName").on("change", function() {
    var post_id = this.value;
    console.log(this);
    $.ajax ({
        url: "_includes/ajax.php",
        type: "POST",
        data: {post_id : post_id},
        dataType: "json",
        success: function(response) {
            $( "input#postid" ).val(response.post_id);
            $( "input#title" ).val(response.post_title);
            $( "textarea#content" ).val(response.post_content);
        },
        failure: function() {
            alert("fail");
        }
    }); 
});

})();
</script>
</section>

<?php include("_includes/footer.php"); ?>

And here is my ajax.php:

<?php require_once("connection.php"); ?>
<?php require_once("functions.php"); ?>
<?php include_once("form_functions.php"); ?>
<?php
//if(isset($_POST['title'])) {
    //$post_id = $_POST['post_id'];
    //$query = "SELECT title, content
    //       FROM posts 
    //       WHERE id = '$post_id'";
    //$result = mysqli_query($connection, $query);
    //$row = mysqli_fetch_array($result);
    //echo $row['title'], $row['content'];
//}
    $post_id = $_POST['post_id'];
    $query = "SELECT *
             FROM posts 
             WHERE id = '$post_id'";
    $result = mysqli_query($connection, $query);
    $row = mysqli_fetch_array($result);
    echo json_encode(
        array("post_id" => $row['id'], 
        "post_title" => $row['title'],
        "post_content" => $row['content'])
    )

    //echo $row['title'], $row['content'];
?>


<?php mysqli_close($connection); ?>
Bill
  • 11
  • 5
  • 4
    **WARNING!** Your code contains an [SQL injection vulnerability](http://en.wikipedia.org/wiki/SQL_injection) -- you are passing raw, unfiltered, unvalidated user input directly into an SQL string. SQL injection is [very easy to fix](http://stackoverflow.com/q/60174/168868). Consider [switching to PDO](http://php.net/book.pdo) or [mysqli](http://php.net/book.mysqli) so you can use [prepared statements with parameterized queries](http://en.wikipedia.org/wiki/Prepared_statement). – Charles Jan 03 '13 at 22:27
  • @Charles He is using `mysqli`, read his code. But yes, he should be using [mysqli_real_escape_string](http://nz1.php.net/mysqli_real_escape_string) on all variables before putting them into an SQL query. –  Jan 03 '13 at 22:29
  • I'm actually using the function I created mysql_prep located in my functions file which escapes all the bad stuff. I am using mysqli. – Bill Jan 03 '13 at 22:29
  • 1
    **DON'T** create your own escaping methods or wrappers. **DO** use the [SQL placeholder system](http://bobby-tables.com/php) to make it extremely clear that your data is escaped. Since you're using `mysqli` this is actually very easy, and even easier than what you're doing. – tadman Jan 03 '13 at 22:30
  • Yeah, copy/paste notice. @Triton, you *aren't* filtering data in your second snippet, "ajax.php" – Charles Jan 03 '13 at 22:33
  • I'm using mysqli_real_escape_string in my functions under the function mysql_prep($variable) which passes the POST data as an argument, is this not a correct way to do it outside of escaping each POST? I can do either way, whichever is most secure. – Bill Jan 03 '13 at 22:33
  • @charles, I haven't gotten that far yet. I wanted to get an update working before I escaped those. – Bill Jan 03 '13 at 22:34
  • @charles, thank you for the links as well. – Bill Jan 03 '13 at 22:42
  • You'll notice that in your first block of code you *probably* escape everything properly, but in the second block you forget to do `$post_id` correctly. A single mistake like this can ruin your day, if not your career. This is why it's extremely important to use SQL placeholders. Look at the features of this [automatic SQL takeover tool](http://sqlmap.org/) if you think I'm exaggerating about the risks. – tadman Jan 04 '13 at 15:57
  • 1
    @tadman Thanks for the read. Like I said, I'm new to all this and luckily this initial site I'm building is for family and they're the only one's who will enter any info and such. All of your suggestions I've taken seriously and have modified much of my code to reflect a better way of doing things. Again, many thinks for all your objective and constructive criticism. – Bill Jan 04 '13 at 17:31

1 Answers1

0

Figured it out, in my UPDATE posts SET I had a comma after my second row update. Thank you all for the suggested readings as well.

Bill
  • 11
  • 5