Inseting in database problem with OOP PDO

I’m learning PDO and I want to insert data from form into database using class but it’s not working.

Here are the pages:

connect.php


class Connection {

    public function __construct() {
        $dsn = "mysql:host=localhost;dbname=nascms";
        $user = "root";
        $password = "";

        try {
            @$pdo = new PDO($dsn, $user, $password);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        } catch (PDOException $exc) {
            echo $exc->getMessage();
            exit();
        }
    }

}
$connection=new Connection;

insertPost.php


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Insert new post</title>
    </head>
    <body>
        <form method="post" action="insertPost.php" enctype="multipart/form-data" >
            <table align="center" border="1" width="500">
                <tr>
                    <td align="center" colspan="6" bgcolor="yellow"><h1>Insert new post here</h1> </td>
                </tr>
                <tr>

                    <td align="right" >Post title</td>
                    <td><input type="text" name="title" size="50"></td>
                </tr>
                <tr>
                    <td align="right">Post author</td>
                    <td><input type="text" name="author" size="50"></td>
                </tr>
                <tr>
                    <td align="right">Post keywords</td>
                    <td><input type="text" name="keywords" size="50"></td>
                </tr>
                 <tr>
                    <td align="right">Post image</td>
                    <td><input type="file" name="image" size="50"></td>
                </tr>
                <tr>
                    <td align="right">Post content</td>
                    <td><textarea name="content" cols="40" rows="20" ></textarea></td>
                </tr>
                <tr>
                    <td align="center" colspan="6">
                        <input type="submit" name="submit"value="Publish now">
                    </td>
                </tr>
            </table>
        </form>
    </body>
</html>
<?php


if(!empty($_POST['submit']))
{
    require_once 'includes/Posts.php';
     @$title = $_POST['title'];
        @$date = date('d-m-y');
        @$author = $_POST['author'];
        @$keywords = $_POST['keywords'];
        @$image = $_FILES['image']['name'];
        @$image_tmp = $_FILES['image']['tmp_name'];
        @$content = $_POST['content'];

    if(Posts::insert(@$title, @$date, @$author, @$keywords, @$image, @$image_tmp, @$content)){
        echo "Uspesan unos";
    }
}




?>

Posts.php

<?php

require_once 'connect.php';

class Posts {

    public function insert($title, $date, $author, $keywords, $image, $image_tmp, $content) {
        global $connection;


        if (empty($title) or empty($date) or empty($author) or empty($keywords) or empty($content)) {
            echo "<script>alert('fill all the fields')</script>";
            exit();
        } else {
            global $connection;

            //move_uploaded_file($image_tmp, "../images/$image");
            $sql = "INSERT INTO posts VALUES(:post_title,:post_date,:post_author,
                :post_image,:post_keywords,:post_content)" or die();

            $stmt = @$pdo->prepare($sql);
            $stmt->bindParam(":post_title", $title, PDO::PARAM_STR);
            $stmt->bindParam(":post_date", $date, PDO::PARAM_STR);
            $stmt->bindParam(":post_author", $author, PDO::PARAM_STR);
            $stmt->bindParam(":post_image", $image, PDO::PARAM_STR);
            $stmt->bindParam(":post_keywords", $keywords, PDO::PARAM_STR);
            $stmt->bindParam(":post_content", $content, PDO::PARAM_STR);
            $stmt->execute();
        }
    }

}

?>

You’re going to have to be more specific. Are you getting an error? If so, what’s the error message?

In the mean time, one possible issue I noticed after a quick glance is that you’re calling Posts::insert as though it were a static method, but you didn’t define it that way. Try defining it as static.

public static function insert

But again, if you want more specific help, then we need more than “it’s not working.”

Also, after you do finally get this working, there’s a lot more to talk about. Over time, developers have identified both good and bad practices that, when followed, help make long term programming and maintenance easier. Among them:

  • Don’t use global variables.
  • Don’t suppress errors.
  • Don’t mix logic with presentation.
  • Files should either declare symbols or cause side-effects, but not both.

Hello Jeff Mott, thanks for the reply.

Yes, today I found out that global variables are bad in PHP, I saw that people do not recommend it.

Here are the errors:

Notice: Undefined variable: pdo
Fatal error: Call to a member function prepare() on a non-object

I have to say that pictures do upload in the given directory but the database is still empty.

EDIT

I did add the static word in my function but nothing changes.

Ahh, yes. In your Posts class, you’re using $pdo, but you never got that variable from anywhere.

Related, in your Connection class, you set a $pdo variable inside the __construct function, but you never save or return that value, so it disappears when the function finishes.

OK. how can I return it ?

I’ve been using this to do my connection using $PDO that I picked up by reading a book by Larry Ullman a while back. Though I believe he was using mysqli, I just converted it over to PDO.

<?php

# PDO database: only one connection is allowed. 

class Database {

    private $_connection;
    // Store the single instance.
    private static $_instance;

    // Get an instance of the Database.
    // @return Database: 
    public static function getInstance() {
        if (!self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    // Constructor - Build the PDO Connection:
    public function __construct() {
        $db_options = array(
            PDO::ATTR_EMULATE_PREPARES => false                     // important! use actual prepared statements (default: emulate prepared statements)
            , PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION           // throw exceptions on errors (default: stay silent)
            , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC      // fetch associative arrays (default: mixed arrays)
        );
        $this->_connection = new PDO('mysql:host=localhost;dbname=database_name;charset=utf8', 'root', 'your_password', $db_options);       
    }

    // Empty clone magic method to prevent duplication:
    private function __clone() {
        
    }

    // Get the PDO connection:    
    public function getConnection() {
        return $this->_connection;
    }

}


Then to connect to the database you simply would do the follow:

$db = Database::getInstance();
$pdo = $db->getConnection();

Here’s an actual method that I use for one of my classes:

    // Method checks to see if username isn't already taken and returns true if it is already taken:
    public function isUsernameAvailable() {

        // Connect to PDO database:
        $db = Database::getInstance();
        $pdo = $db->getConnection();

        $query = "
            SELECT
                1
            FROM users
            WHERE
                username = :username1
        ";

        $query_params = array(
            ':username1' => $this->username
        );

        // These two statements run the query against your database table.
        $stmt = $pdo->prepare($query);
        $result = $stmt->execute($query_params);

        // The fetch() method returns an array representing the "next" row from
        // the selected results, or false if there are no more rows to fetch.	   	   
        return $row = $stmt->fetch();
        // If a row was returned, then we know a matching username was found in
        // the database already and we should return a boolean value back.	   
    }

and to simplify things even more have some kind of autoload class in a commons.php or utilities.inc.php file, here’s one that I have been using:

// Autoload classes from "classes" directory:
function class_loader($class) {
    require('lib/classes/' . $class . '.php');
}

spl_autoload_register('class_loader');

that way you don’t have to worry about including or requiring your classes in your project, I have heard some arguments over this method of connection to $pdo in tech forums since. However, I see not pitfalls in this methods and I feel it’s secure.

Thanks Strider64.
Your code looks great, I will use it.

Well I’d recommend against Strider64’s approach if you are an aspiring OOP coder. Singleton is not a good design practice, your client code should get an instance of Database Object through dependency injection(either at constructor or method level), rather than relying on singleton class which is technically global.

I have the weirdest error right now, instead of records in database I got inserted number 1.
No matter what I write in the fields I still get number 1 in the database.

EDIT:

I’ve fixed it.

Some of us, most are here to learn. want to share?

I have adjusted my code according this tutorial.

[video=youtube_share;B1_yi7HM0Cg]http://youtu.be/B1_yi7HM0Cg[/video]