PHP get function's result from class itself? - php

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.

Related

PHP- How to get last inserted ID from mysqli query inside a class

I know returning the last inserted ID when running a straight query is simple:
$query = $db->query("INSERT INTO site_stats (PageView) VALUES('1')");
if ($query) {
$id = $db->insert_id;
echo 'The ID is: '.$id;
}
However, I am running all of my queries through a class which helps me keep track of how many queries I am executing and how long it's taking. The class is simple and straightforward:
class dbLog {
public $queries = array();
public function query($sql) {
global $db;
$start = microtime(true);
$query = $db->query($sql);
$this->queries[] = microtime(true) - $start;
return $query;
}
public function getCount() {
return sizeof($this->queries);
}
public function getTime() {
return number_format(array_sum($this->queries), 5);
}
} // end dbLog class
$dbLog = new dbLog;
The problem is, when I run queries through this class, I can not figure out how to return the last inserted ID:
$query = $dbLog->query("INSERT INTO site_stats (PageView) VALUES('1')");
if ($query) {
$id = $dbLog->insert_id;
echo 'The ID is: '.$id; // Returns error
}
The error I get returned is Undefined property: dbLog::$insert_id
How can I get the ID of the last inserted row?
Since your class is just using $db from the global scope, you can use $db->insert_id as you originally did.
To do this in a proper manner you'd want to actually wrap the $db object inside your own class / object, either by extending (inheriting) from the original class and then instantiating your own, or by implementing the methods you want to expose through your own class, and giving $db to the constructor and keeping the reference internally.
You're wrapping the mysqli class in another class (you're also using global, which is not ideal)
What you need is a method to get the ID from the actual mysqli instance
public function getId() {
global $db;
return $db->insert_id;
}
If I were you I'd use dependency injection and make your mysqli instance part of the class itself
class dbLog {
/** #var \mysqli */
protected $db;
public function __construct(\mysqli $db) {
$this->db = $db;
}
public function query($sql) {
$start = microtime(true);
$query = $this->db->query($sql);
$this->queries[] = microtime(true) - $start;
return $query;
}
public function getId() {
return $this->db->insert_id;
}
}

PHP Database class - select function

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
}

is that nested methods right? why I get empty query?

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.

PHP singleton pattern

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');
}

Using SQL function from SQL handling class in other functions

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');
}

Categories