I wonder why I get errors with that code? Can Someone help?
My class is to get some information from database using nested methods,suppose I get an empty query
<?php
class db {
public function __construct(){
if(mysql_connect("localhost","root","0000")){
mysql_select_db("myblog");
}else{
echo mysql_error();
}
}
public function select($row){
$sql="SELECT".$row;
return $this;
}
public function from($table){
$sql.="FROM".$table;
return $this;
}
public function where($condition){
$sql.="WHERE".$condition;
return $this;
}
}
$ddb=new db;
$qq=$ddb->select("*")->from("news")->where("id='1'");
$query= mysql_query($qq);
while($row=mysql_fetch_object($query)){
echo $row->title;
}
?>
You have to define __toString() special method to use your object as a string:
class db {
private $sql = '';
public function __construct() {
if (mysql_connect("localhost", "root", "0000")) {
mysql_select_db("myblog");
} else {
echo mysql_error();
}
}
public function select($row) {
$this->sql = "SELECT ".$row;
return $this;
}
public function from($table) {
$this->sql .= " FROM ".$table;
return $this;
}
public function where($condition) {
$this->sql .= " WHERE ".$condition;
return $this;
}
public function __toString() {
return $this->sql;
}
}
$ddb = new db();
$qq = $ddb->select("*")->from("news")->where("id='1'");
$query = mysql_query($qq);
while ($row = mysql_fetch_object($query)) {
echo $row->title;
}
You need to be using $this in each of the methods to append to $sql
// Declare the class property
public $sql = "";
// And use $this->sql in the methods
// Also note whitespace added around SELECT, FROM, WHERE
public function select($row){
$this->sql="SELECT ".$row;
return $this;
}
public function from($table){
$this->sql.=" FROM ".$table;
return $this;
}
public function where($condition){
$this->sql.=" WHERE ".$condition;
return $this;
}
Then when you query it, use $ddb->sql, since you are not returning the SQL string.
$ddb->select("*")->from("news")->where("id='1'");
$query = mysql_query($ddb->sql);
And it goes without saying that hopefully you intend to be calling mysql_real_escape_string() on any variables you construct into your where() method. As it is, you have no particular escaping on it.
run a var_dump on $qq
That will show you the problem instantly.
To me it looks as if you are missing a couple of spaces in your query and that you aren't returning the query string $sql but instead $this in your db class
use $this->sql instead of $sql in the methods select, from, where
output the query like this: $ddb->select("*")->from("news")->where("id='1'")->sql or create a getSQL() method which just returns the $sql field and query it like $ddb->select("*")->from("news")->where("id='1'")->getSQL()
You should also consider creating a method which creates a mysql_query (not just the string) or some methods for retrieving methods, so it's easier to use.
Related
I worked with procedural PHP for a long time but not to long ago I just started to learn OOP PHP. For better understanding I decided to create a class to manage my DB. As I started to learn from phpacademy my first select function was quite poor, so I just added some other arguments. I ended up with this:
public function get($tabel, $where = null, $columns = array('*'), $other = null){
if($where){ $where = $this->where($where);; }
$select = 'SELECT '.$this->select($columns);
return $this->action($select, $tabel, $where, $other);
}
// $db->get('users',array('group',1),array(*),array('LIMIT' => 10));
(action executes the query)
Then I decided to modify this to get better control.
public function getModified($table, $param = array()){
$select = (isset($param['S'])) ? $this->select($param['S']) : '*';
$where = (isset($param['W'])) ? $param['W'] : array();
$other = array();
if(isset($param['GB'])){ $other['GROUP BY'] = $param['GB']; }
if(isset($param['OB'])){ $other['ORDER BY'] = $param['OB']; }
if(isset($param['L'])){ $other['LIMIT'] = $param['L']; }
return $this->action('SELECT '.$select, $table, $where, $other);
}
// $db->getModified('users',array('WHERE' => array('id',1), 'LIMIT' => 10));
But today I found in FuelPHP's documentation this: DB::get()->from('users')->where('id', 1)->limit(10);
Because I do this class to practice OOP PHP I've tried to create something similar but to execute the query I had to add an other function, which I want to skip. Could you show me an example how this method should/could work?
And I know that it's objective but which one would you prefer?
I'll just explain how the FuelPHP way works. This is btw a pattern that is used in a lot of DB wrapper classes.
In short, your Database package consists of 2 classes. 1 that handles connection to your database, multiple connections,... This is the DB class. this will look something like this:
class DB
{
private static $connections = array();
public static function addConnection($name, $connection)
{
self::$connection[$name] = $connection;
}
public static function get($name='default')
{
return new QueryBuilder(self::$connection[$name]);
}
}
This class manages all connections and returns a queryBuilder instance if you need to query a connection. The QueryBuilder will look something like this:
class QueryBuilder
{
private $connection;
public function __construct($connection)
{
$this->connection = $connection;
}
public function select()
{
$this->queryType = 'SELECT';
return $this;
}
public function from($table)
{
$this->table = $table;
return $this;
}
public function all()
{
return $this->connection->query(
$this->getSqlQuery()
);
}
public function getSqlQuery()
{
return $this->queryType . ' ' . $this->columns . ' FROM ' . $this->table;
}
}
so now you can use the clases above as:
DB::setConnection('default', $myPdoConnection);
DB::get()->select()->from('my_table')->all();
Note that the Querybuilder assumes that your $connection has a query method
A nice example from the Eloquent/laravel QueryBuilder: https://github.com/illuminate/database/blob/master/Query/Builder.php
What you are searching for is method chaining, also fuelphp (just like doctrine and others) is caching what you are sending in and builds the query after that:
public function from($table){
$this->_table = $table;
return $this; //this is the important part for chaining
}
public function where($key,$value){
$this->where = array($key => $value);
return $this;
}
public function andWhere($key,$value){
if(!$this->where) $this->where = array();
$this->where[$key] = $value;
return $this;
}
public function getQuery(){
//Build query here from what we stored before
$query = '';
....
return $query;
}
Oh well, what i forgot is what DB::get returns, an instance of what the class above is and executes that then:
public static function get(){
return new Query(); //above functions are part of Query class
}
I'm wondering how to receive the results from a function "from the class itself". An example of this is the PDO functions, where I can do the following to get i.e. the last ID:
$db->query($sql);
$id = $db->lastInsertId();
Right now I have to do the following:
$newThread = $forums->newThread('title','category');
$id = $newThread['id'];
Of course this works great, but I have to use the variable $newThread, which I don't want to. How do I save the value in order to call it later?
In case you have problems understanding how the PDO version works, it's roughly like this:
class PDO {
private $lastInsertId;
public function query($sql) {
magic_sql_api_call($sql);
/* here be dragons */
$this->lastInsertId = magic_sql_api_get_last_insert_id();
}
public function lastInsertId() {
return $this->lastInsertId;
}
}
You can create code like this
class Forums {
private $id;
...
function createTread($title, $category) {
$newThread = $forums->newThread($title, $category);
$this->id = $newThread['id'];
}
function lastId() {
return $this->id;
}
}
You can use it
$forums->createTread('title','category');
$id = $forums->lastId();
You probably will need to save $newThread in property too.
I'm a little confused at the moment because my DB class doesn't seem to be storing any results after a query (i.e. the 'results' property is still an empty array). The unsual thing is that when I transfer my logic outside a class definition it works perfectly.
My code with database credentials blanked out:
namespace DatabaseConnection;
use PDO;
class DB {
/*****STATES*****/
private $con;
private $results;
/*****METHODS*****/
public function init(){
$this->con = new PDO("***************************");
$this->results = array();
return $this;
}
public function getInfo(){
if($this->con === null ) return "No Connection";
else return "Connected";
}
public function getResults(){
return $this->results;
}
public function retrieve(){
$query = $this->con->prepare("select * from documents");
$query->execute();
while($row = $query->fetch(PDO::FETCH_ASSOC)){
$this->results[] = $row;
}
return $this;
}
Try:
public function retrieve(){
$query = $this->con->prepare("select * from documents");
$query->execute(); //<---------
while($row = $query->fetch(PDO::FETCH_ASSOC)){
$this->results[] = $row;
}
return $this;
}
OP is preparing a statement and then never executes it, and has no way of detecting this because of the utter lack of any error handling on the DB calls. – Marc B
Hello there i want to learn a singleton pattern in php,
i have a class:
class Database
{
private static $instance;
private function __construct()
{
}
public static function getInstance()
{
if (!self::$instance)
{
self::$instance= new Database();
}
return self::$instance;
}
public function query($table)
{
$this->query = 'select * from $table';
}
public function result()
{
echo $this->query;
}
}
$db = Database::getInstance();
and now , is it posible to call the result() method and print the value set by the query() which is "select * from $table" using a singleton?
i want my code in something like:
$db->query('user_tb')->result();
//output
select * from user_tb;
Update:
To be able to call it like:
$db->query('user_tb')->result();
You need to put return $this; in method you want to chain, in this case your query method:
public function query($table)
{
$this->query = "select * from $table";
return $this;
}
Now you can call it like : $db->query('user_tb')->result();
Working Example
-------------------------------------------------------------------------------------------
First modify in your query() method:
$this->query = 'select * from $table';
To:
$this->query = 'select * from ' . $table;
since inside single quotes, variables are not parsed.
And then define $query at class level like this:
class Database {
private static $Instance;
private $query = '';
// your more code
}
And then you can run this to get it:
$db = Database::getInstance(); // get class instance
$db->query('user_tb'); // set $query var
$db->result(); // get $query var
Result:
select * from user_tb
Working Example
To use method chaining, make sure all functions you want to chain return $this.
Then you can do DB::getInstance()->query()->result();.=
So query at least needs to return $this.
Also, you forgo any error handling by return parameter, so generally if you use method chaining you need to use exception handling to deal with errors.
As in, you can't do
if(!$db->query) {
error_log('bleh');
}
I have created an SQL function SQLquery in a class called SQLHandling
It looks like this:
/***********************************************************
* SQLquery takes a full SQL query and runs it
* If it fails it will return an error otherwise it will return
* the SQL query as given.
************************************************************/
function SQLquery($query) {
$q = mysql_query($query);
if(!$q) {
die(mysql_error());
return false;
} else {
return $q;
}
}
Is there anyway I can use this function in other classes functions without adding
$db = new SQLHandling();
$db->SQLquery($sql);
In every function where I will use it.
I know I can run SQLHandling::SQLquery($sql); but I am trying to avoid that.
use inheritance
refer:
http://php.net/manual/en/language.oop5.inheritance.php
but still you will need to use parent::fun() or $this->fun()
or put it as a public function then use any where.
example:
<?php
function c()
{
echo "moi";
}
class b extends a
{
public function d(){
parent::c();//Hai
$this->c();//Hai
c();//moi
}
}
class a{
public function c(){
echo "Hai";
}
}
$kk = new b();
$kk -> d();
?>
You could instantiate SQLHandling on class level, like so:
private $db;
public function __construct()
{
$this->db = new SQLHandling();
}
public function x()
{
$this->db->query('X');
}