Yuri Blanc
Yuri Blanc

Reputation: 645

PDO fetch single class not working

i am making a database abstraction class that binds objects like an ORM. I'm having issue with a particular case, fetching a single row and binding to a class. While the same is working well with fetchAll() i can't figure out why using fetch(PDO::FETCH_CLASS) the object returns null. if i use PDO::FETCH_LAZY it works, but isn't a correct binding to the passed class. Here the code. The Database() class is connects to db using PDO. Products() is a class made of public attributes with same name of tables. The controller:

public function editProducts($params) {
    $products = new Products();
    $db = new Database ();
    $id = array_keys($params);
    $products = $db->findById($products, $id[0]); // auto Bind object fetched=no and POST params?
    $this->template = new Template();
    $this->template->renderArgs("product", $products);
    $this->template->renderArgs("page_title", "Edit product " . $products->title);
    $this->template->render(get_class($this), "editProducts");

}

The DB class:

public function findById($object,$id) {
    try {
    $table = $this->objectInjector($object);
    } catch (Exception $e) {
        if (APP_DEBUG) {
            d($e->getTrace());
        }
        return;
    }
    $statement = "SELECT * FROM $table WHERE id=:id";
    $this->stm = $this->pdo->prepare($statement);
    $this->bindValue(":id",$id);
    return $this->fetchSingleObject($object);
}

the method that abstract fetch:

public function fetchSingleObject($object) {
    $this->execute();
    $this->stm->setFetchMode(PDO::FETCH_CLASS, get_class($object));
    return $this->stm->fetch(PDO::FETCH_CLASS);
    //return $this->stm->fetch(PDO::FETCH_LAZY); this works!
}

I missed something? the fetchAll() works nicely in this way:

 public function fetchObjectSet($object) {
        $this->execute();
        $this->stm->setFetchMode(PDO::FETCH_CLASS, get_class($object));
        return $this->stm->fetchAll(PDO::FETCH_CLASS);
    }

Thank you so much. PS: some methods like $this->execute() are just abastractions to pdo->statment method since pdo and stm are db class instance variables.

Upvotes: 2

Views: 2437

Answers (2)

Yuri Blanc
Yuri Blanc

Reputation: 645

I found the answer to the question by myself, i post the answer for everyone.

Instead of using directly PDO::FETCH_CLASS, $Class, i switched using setFetchMode() passing PDO_FETCH_INTO, new $Object instance.

This return correctly new instance of given object (with object methods and fields). Works well with public attributes and overloaded constructors.

The previously statement "findAll() works" wasn't true, i was returning somehow like FETCH_OBJ, an object representation of the database table.

Here the solution:

public function fetchSingleObject($object) {
    $this->stm->setFetchMode(PDO::FETCH_INTO, new $object());
    $this->execute();
    return $this->stm->fetch();
}

Return a new instance of passed in object.

Works also as fetchAll()

EDIT:

public function fetchObjectSet($object) {

    $this->execute();
    return $this->stm->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, get_class($object));
}

Upvotes: 4

Professor Abronsius
Professor Abronsius

Reputation: 33813

The manual states:

bool PDOStatement::setFetchMode ( int $PDO::FETCH_CLASS , string $classname , array $ctorargs )

so perhaps try:

$this->stm->setFetchMode(PDO::FETCH_CLASS, 'get_class', $object );/* is $object an array ? */
or, without
$this->stm->setFetchMode(PDO::FETCH_CLASS, 'get_class' );

Upvotes: -1

Related Questions