Jump to content

PDO Syntax problem


Recommended Posts

I'm trying to call a PDO fetch from within a class I'm writing, however I have never used PDO and the documentation @ php.net is somewhat...crap.  It's probably fine for people who just need a refference, but navigating it as a learning resource isn't the easiest.  Anyway, I keep getting

Fatal error: Call to undefined method PDO::fetch() in C:\xampp\htdocs\eclipse\src\connect.php on line 85
I can post up the class if you like, but it's something of a mess to follow. This is the method that's calling the fetch :
	public function get($method='ASSOC'){
	if($this->temp !== null){
		$this->run(); //performs PDOexecute and returns resourcce to $this->resource
		$qry = $this->resource;
		if($this->rdbs == 'mysql'){
		$fetch= "FETCH_".strtoupper($method); //builds the fetch type from parameter, or uses ASSOC as default.
/*Ln85------------>>*/	$this->result = $this->dbo->fetch(PDO::$fetch); //performs the PDO search using the $this->dbo which is the public class PDO Object 
		}// the stuff under here isn't used (yet) and isn't in PDO, since MS SQL Server is not supported by PDO
		elseif($this->rdbs == 'mssql'){
			$fetch = "SQLSRV_FETCH_".strtoupper($method);
			$this->result = sqlsrv_fetch_array($qry, $fetch);
			$this->num_rows = sqlsrv_num_rows($qry);
		}
	}

I built the call to mirror what I could find on the php.net site, but obviously that's not what's happening here.  Can anyone point out what part of this I have screwed up? (I don't mind if the answer's all of it, so long as it comes with an explination ;) )

Link to comment
Share on other sites

I think the reference is pretty good, you just need to learn how to read it. If you read carefully, it says that the ::fetch() method belongs to PDOStatement class, not PDO. So you first must run the query, which in turn will give you a PDOStatement object you can use the fetch on.

 

Is $qry your returned result set? Then use ::fetch on it.

Link to comment
Share on other sites

cheers silkfire.  I must be getting all mixed up here.  $qry is as I see it the resource returned from the PDO->execute, I thought that PDO::fetch was what generated the result set  :shrug:

 

I tried running the fetch against $qry and got : Call to a member function fetch() on a non-object

 

Here's the class in it's entirety so you can maybe see what I'm doing (it's still a work in progress so please be gentle)

<?php 
class dbc {
public $dbo;
public $rdbs;
public $temp;
public $result;
public $num_rows;
public $resource;
public $con;

public function __construct($type, $con=null){
	$this->temp = null;
		if(strtolower($type) == 'mysql'){
			$this->establish_MySQL($con);
		}
		if(strtolower($type) == 'mssql'){
			$this->establish_MSSQL($con);
		}
}

public function establish_MySQL($con){
	if($con === null){
		if(!defined('_HOST') || !defined('_USER') || !defined('_PASS') || !defined('_DB')){
			exit;
		}
		$dsn = "mysql:host={_HOST};dbname={_DB}";
		$this->dbo = new PDO($dsn, _USER, _PASS);
		$this->rdbs = 'mysql';
	}
	else{
		$dsn = "mysql:host={$con['host']};dbname={$con['db']}";
		$this->dbo = new PDO($dsn, $con['user'], $con['pass']);
		$this->rdbs = 'mysql';
	}
}

public function establish_MSSQL($con){
	if($con === null){
		if(!defined('_HOST') || !defined('_USER') || !defined('_PASS') || !defined('_DB')){
			exit;
		}
		$dsn = "{_HOST}";
		$this->dbo = sqlsrv_connect($dsn, array('Database'=>_DB, 'UID'=>_USER, 'PWD'=>_PASS));
		$this->con = $this->dbo;
		$this->rdbs = 'mssql';
	}
	else{
		$dsn = "{$con['host']}";
		$this->dbo = sqlsrv_connect($dsn, array('Database'=>$con['db'],'USR'=>$con['user'], 'PWD'=>$con['pass']));
		$this->con = $this->dbo;
		$this->rdbs = 'mssql';
	}
}

public function build($string, $params){
	if($this->rdbs == 'mysql'){
		$prep = $this->dbo->prepare($string);
		foreach($params as $key => $value){
			$prep->bindParam($key, $value);
		}
		$this->temp = $prep;
	}
	elseif($this->rdbs == 'mssql'){
		$this->temp = sqlsrv_prepare($this->dbo, $string, $params);
	}
}

public function run(){
	if($this->temp !== null){
		if($this->rdbs == 'mysql'){
			$this->resouce = $this->temp->execute();
		}
		elseif($this->rdbs == 'mssql'){
		 $this->resource = sqlsrv_execute($this->con,$this->temp);	
		}
	}
}

public function get($method='ASSOC'){
	if($this->temp !== null){
		$pdo = $this->dbo;
		$this->run();
		$qry = $this->resource;
		if($this->rdbs == 'mysql'){
			$fetch= "FETCH_".strtoupper($method);
			$this->result = $qry->fetch(PDO::$fetch);
		}
		elseif($this->rdbs == 'mssql'){
			$fetch = "SQLSRV_FETCH_".strtoupper($method);
			$this->result = sqlsrv_fetch_array($qry, $fetch);
			$this->num_rows = sqlsrv_num_rows($qry);
		}
	}
}

public function exec(){
	if($this->temp !== null){
		$this->run();

		if($this->rdbs == 'mysql'){
			$this->num_rows = $this->resource->rowcount();
		}
		elseif($this->rdbs == 'mssql'){
			$this->num_rows = sqlsrv_rows_affected($this->resource);
		}
	}
}


}
?>

Link to comment
Share on other sites

You're a veteran mate you're the one with more knowledge lol =)

 

Once again, ::execute belongs to the PDOStatement class, but returns a bool, thus ($this->resource is a bool!) your error that you're trying to use a class method on a bool =D

 

I can see in your code that you've saved the resouce in $prep ($this->temp) actually! So it's a matter of some minor changes and it should work.

 

But I agree with you sometimes very obvious errors are invisible to the author but obvious to someone who sees the code for the first time.

Link to comment
Share on other sites

Lol I can immediately see the cause of all your errors mate!

 

PDO has a list of constants that correspond to numbers (see list here: http://www.php.net/manual/en/pdo.constants.php). You're trying to use the PDO::FETCH_* in string form!

 

If I were you I'd make a mapping array but maybe this syntax works as well: PDO::{$fetch}, not sure though.

 

$fetch_methods = array(
                       'assoc'      => PDO::FETCH_ASSOC,
                       'lazy'       => PDO::FETCH_LAZY,
                       'named'      => PDO::FETCH_NAMED,
                       'num'        => PDO::FETCH_NUM,
                       'both'       => PDO::FETCH_BOTH,
                       'obj'        => PDO::FETCH_OBJ,
                       'bound'      => PDO::FETCH_BOUND,
                       'column'     => PDO::FETCH_COLUMN,
                       'class'      => PDO::FETCH_CLASS,
                       'into'       => PDO::FETCH_INTO,
                       'func'       => PDO::FETCH_FUNC,
                       'group'      => PDO::FETCH_GROUP,
                       'unique'     => PDO::FETCH_UNIQUE,
                       'serialize'  => PDO::FETCH_SERIALIZE,
                       'props_late' => PDO::FETCH_PROPS_LATE
                      );

...

if (isset($fetch_methods[strtolower($method)]))
   $method = $fetch_methods[strtolower($method)]);
else
   $method = $fetch_methods['assoc']);

Link to comment
Share on other sites

You're welcome! Good luck with that one ;)

 

By the way there were errors in my code plus I missed 2 fetch constants so here's the correct code:

 

$fetch_methods = array(
                       'assoc'      => PDO::FETCH_ASSOC,
                       'lazy'       => PDO::FETCH_LAZY,
                       'named'      => PDO::FETCH_NAMED,
                       'num'        => PDO::FETCH_NUM,
                       'both'       => PDO::FETCH_BOTH,
                       'obj'        => PDO::FETCH_OBJ,
                       'bound'      => PDO::FETCH_BOUND,
                       'column'     => PDO::FETCH_COLUMN,
                       'class'      => PDO::FETCH_CLASS,
                       'into'       => PDO::FETCH_INTO,
                       'func'       => PDO::FETCH_FUNC,
                       'group'      => PDO::FETCH_GROUP,
                       'unique'     => PDO::FETCH_UNIQUE,
                       'key_pair'   => PDO::FETCH_KEY_PAIR,
                       'classtype'  => PDO::FETCH_CLASSTYPE,
                       'serialize'  => PDO::FETCH_SERIALIZE,
                       'props_late' => PDO::FETCH_PROPS_LATE
                      );

...

if (isset($fetch_methods[strtolower($method)]))
   $method = $fetch_methods[strtolower($method)];
else
   $method = $fetch_methods['assoc'];

Link to comment
Share on other sites

cheers for the update.

 

Yeah, I *kinda* get the difference between bind param and bind value, I fixed the problem using a duplicate style of the array you posted for the fetch params, the problem I was having was that I wasn't passing in any param types to the binding method.

 

so now the class looks like this:

<?php 
class dbc {
public $dbo;
public $rdbs;
public $temp;
public $result;
public $num_rows;
public $resource;
public $con;

public function __construct($type, $con=null){
	$this->temp = null;
		if(strtolower($type) == 'mysql'){
			$this->establish_MySQL($con);
		}
		if(strtolower($type) == 'mssql'){
			$this->establish_MSSQL($con);
		}
}

public function establish_MySQL($con){
	if($con === null){
		if(!defined('_HOST') || !defined('_USER') || !defined('_PASS') || !defined('_DB')){
			exit;
		}
		$dsn = "mysql:host={_HOST};dbname={_DB}";
		$this->dbo = new PDO($dsn, _USER, _PASS);
		$this->rdbs = 'mysql';
	}
	else{
		$dsn = "mysql:host={$con['host']};dbname={$con['db']}";
		$this->dbo = new PDO($dsn, $con['user'], $con['pass']);
		$this->rdbs = 'mysql';
	}
}

public function establish_MSSQL($con){
	if($con === null){
		if(!defined('_HOST') || !defined('_USER') || !defined('_PASS') || !defined('_DB')){
			exit;
		}
		$dsn = "{_HOST}";
		$this->dbo = sqlsrv_connect($dsn, array('Database'=>_DB, 'UID'=>_USER, 'PWD'=>_PASS));
		$this->con = $this->dbo;
		$this->rdbs = 'mssql';
	}
	else{
		$dsn = "{$con['host']}";
		$this->dbo = sqlsrv_connect($dsn, array('Database'=>$con['db'],'USR'=>$con['user'], 'PWD'=>$con['pass']));
		$this->con = $this->dbo;
		$this->rdbs = 'mssql';
	}
}

public function build($string, $params){
	$paramType = array(
		'bool'=> PDO::PARAM_BOOL,
		'null'=>PDO::PARAM_NULL,
		'int'=>PDO::PARAM_INT,
		'str'=>PDO::PARAM_STR,
		'lob'=>PDO::PARAM_LOB
	);
	if($this->rdbs == 'mysql'){	
		$pdo_param = PDO::PARAM_STR; 
		$prep = $this->dbo->prepare($string);
		foreach($params as $set){
			foreach($set as $key => $value){
				if(strtolower($key) == 'param' || $key == 0){
					$para = $value;
				}
				if (strtolower($key) == 'value' || $key == 1){
					$val = $value;	
				}
				if(strtolower($key) == 'type' || $key == 2){
					$pdo_param = $paramType[$value];
				}
				$prep->bindParam($para, $val, $pdo_param);
			}

		}
		$this->temp = $prep;
	}
	elseif($this->rdbs == 'mssql'){
		$this->temp = sqlsrv_prepare($this->dbo, $string, $params);
	}
}

public function run(){
	if($this->temp !== null){
		if($this->rdbs == 'mysql'){
			$this->resource = $this->temp->execute();
		}
		elseif($this->rdbs == 'mssql'){
		 $this->resource = sqlsrv_execute($this->con,$this->temp);	
		}
	}
}

public function get($method='assoc'){
	$fetch_methods = array(
			'assoc'      => PDO::FETCH_ASSOC,
			'lazy'       => PDO::FETCH_LAZY,
			'named'      => PDO::FETCH_NAMED,
			'num'        => PDO::FETCH_NUM,
			'both'       => PDO::FETCH_BOTH,
			'obj'        => PDO::FETCH_OBJ,
			'bound'      => PDO::FETCH_BOUND,
			'column'     => PDO::FETCH_COLUMN,
			'class'      => PDO::FETCH_CLASS,
			'into'       => PDO::FETCH_INTO,
			'func'       => PDO::FETCH_FUNC,
			'group'      => PDO::FETCH_GROUP,
			'unique'     => PDO::FETCH_UNIQUE,
			'serialize'  => PDO::FETCH_SERIALIZE,
			'props_late' => PDO::FETCH_PROPS_LATE
	);
	$pdo_method = $fetch_methods[$method];
	if($this->temp !== null){
		$pdo = $this->dbo;
		$this->run();
		$qry = $this->resource;
		if($this->rdbs == 'mysql'){
			$fetch= "FETCH_".strtoupper($method).":";
			$this->result = $this->temp->fetch($pdo_method);
		}
		elseif($this->rdbs == 'mssql'){
			$fetch = "SQLSRV_FETCH_".strtoupper($method);
			$this->result = sqlsrv_fetch_array($qry, $fetch);
			$this->num_rows = sqlsrv_num_rows($qry);
		}
	}
}

public function exec(){
	if($this->temp !== null){
		$this->run();

		if($this->rdbs == 'mysql'){
			$this->num_rows = $this->resource->rowcount();
		}
		elseif($this->rdbs == 'mssql'){
			$this->num_rows = sqlsrv_rows_affected($this->resource);
		}
	}
}


}
?>

I'll add in the other constants shortly. but for the most part the PDO side of things is working - have yet to try the exec() method to perform an insert, but I'm thinking it should manage ok. I've not added the error capture or comments yet, and I've still to go through and set the scope properly.

 

I'll be testing the sqlsrv side of the class soon, so will no doubt be back on when I get to that :)

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.