Search code examples
phpmysqliscoping

Php class not allowing class-wide scoping


I can't figure out the below code, why it isn't working.

/classes/ContentManager.php

<?php
class ContentManager{
    protected $sql;
    protected $host     = "<correct host>";
    protected $username = "<correct username>";
    protected $password = "<correct password";
    protected $dbname   = "<correct dbname>";

    protected $query;
    protected $addquery = "INSERT INTO Content (Page, ElementID, Text) VALUES (?, ?, ?)";
    protected $grabquery    = "SELECT ElementID, Text FROM Content WHERE Page = ?";
    public function __construct(){

        $this->sql = new mysqli($this->host, $this->username, $this->password, $this->dbname);

        if(mysqli_connect_errno())
            die("Connection to DB failed, please contact web administrator at: [email protected]");


    }

    public function add($page, $element_id, $text){
        if($this->query = $this->sql->prepare($this->addquery)){
            $this->query->bind_param("sss", $page, $element_id, $text);
            $this->query->execute();
            $this->query->close();
        }
    }

    public function grab($page){
        if($this->query = $this->sql->prepare($this->grabquery)){
            $this->query->bind_param("s", $page);
            $this->query->execute();
            $this->query->bind_results($elementID, $text);
            $results = array();
            while($row = $this->query->fetch_assoc()){
                $results[] = $row;
            }
        }
        return $results;
    }

    public function __destruct(){
        $this->sql->close();
    }
}
?>

I had originally not used it as a property but instead had it declared within the class but that wasn't working either. Why is this?


EDIT This is the code inserts the data for the test:
testcrm.php

<?php
    phpinfo();
spl_autoload_register('classloader');

function classloader($className){
    include ("/classes/".$className.".php");
}

$content = new ContentManager();

$action = $_GET['func'];
if($action==='add'){
    $content->add($_GET['page'], $_GET['id'], $_GET['content']);
}

?>

And here is the test url:
testcrm.php?func=add&page=testcrm&id=divcontainer&content=<h1>test</h1>


Solution

  • The way you have written your code, if the query fails, you'll never know. It just silently returns from your add() function even if it didn't do anything.

    You should always do something to report the error if your prepare() or execute() fails. These functions return false if there's a problem, and if that happens you should output the error (or at least log the error even if you want to show only a friendlier "we are experiencing technical difficulties" screen to users).

    Here's an example:

    public function add($page, $element_id, $text){
        if(($this->query = $this->sql->prepare($this->addquery)) === false){
            trigger_error($this->sql->error, E_USER_ERROR);
        }
        $this->query->bind_param("sss", $page, $element_id, $text);
        if ($this->query->execute() === false)) {
            trigger_error($this->query->error, E_USER_ERROR);
        }
        $this->query->close();
    }
    

    Do something similar for both prepare() and execute() in your grab() function too, and every time you prepare or execute an SQL statement. It's tedious, but necessary.

    Mysqli is supposed to have a capability to report errors by throwing exceptions, but this isn't enabled by default. You can read more about it here: http://www.php.net/manual/en/mysqli-driver.report-mode.php