Jump to content

Recommended Posts

Hey Guys. Quick question about using affected_rows OOP style. When I define the following method:

public function affected_rows() {
        return $this->_connection->affected_rows;
    }

 

in my MySQLDatabase class and call it from a different class it displays the affected rows.

 

 Want I want is to  call affected rows from the MySQLDatabase with out having a method in it. I want to use what mysqli returned back to me. Is there anyway where I can do that?

 

Below is the following code I am using to call the affected rows from the other classes...

 

Thanks for your help in advance :happy-04:

public function update($table_name, $attributes,$id) {
           global $database;
          $attribute_pairs = array(); 
          foreach($attributes as $key => $value) {
          $attribute_pairs[] = "{$key}='{$value}'"; }
          
          $sql = "UPDATE {$table_name} SET ";
          $sql .= join(", ",  $attribute_pairs);
          $sql .= "WHERE id = {$id} ";
          $result = $database->query($sql);
          return $result->affected_rows == 1 ? true : false;

Below is my whole MySQLDatabase class ($database)

<?php
require('config.php');

class MySQLDatabase {
    
    private $_connection;
    public $last_query;
    private $magic_quotes_active;
    private $real_escape_string_exists;
 
    public function __construct() {
        //$this->_connection = new mysqli($host, $user, $password, $database, $port, $socket)
        $this->_connection =  new mysqli('localhost', 'root');
        if(!$this->_connection) {die('Connection Error'.$_connection->connect_error );
        } else {
            $db_select = $this->_connection->select_db(DB_NAME);
        } if(!$db_select) {
            die("Database Selection Failed" . $this->_connection->error);
        }
        
           $this->magic_quotes_active = get_magic_quotes_gpc();
           $this->real_escape_string_exists = function_exists( "mysql_real_escape_string" );
    }
    
    public function query($sql) {
        $this->last_query = $sql;
        $result = $this->_connection->query($sql);
        $this->confirm_query($result);
        return $result;
    }
    
    
    
    
    //Database Nuteral Methods
    
    private function confirm_query($result){
    if(!$result) {
        $output = "Database query failed: ";
        $output .=  "Last query ". $this->last_query;
            die($output);
    
      }
    }
    
    public function num_rows($result_set) {
        $this->_connection->num_rows($result_set);
       
    }
    
    public function insert_id() {
        //Get the last ID inserted over the database 
        return $this->_connection->insert_id();
        
    }
    
    public function affected_rows() {
        return $this->_connection->affected_rows;
    }


//Database Netural Methods

    public function __clone(){} 

            public function escape_value( $value ) {
                  if( $this->real_escape_string_exists) { // PHP v4.3.0 or higher
			// undo any magic quote effects so mysql_real_escape_string can do the work
	        if( $this->magic_quotes_active ) { $value = stripslashes( $value ); }
	       $value = mysql_real_escape_string( $value );
		} else { // before PHP v4.3.0
			// if magic quotes aren't already on then add slashes manually
	                   if( !$this->magic_quotes_active ) { $value = addslashes( $value ); }
			// if magic quotes are active, then the slashes already exist
		        }
		           return $value;
	               }
    
  
  
    
    public function close_connection(){
         if(isset($this->_connection)) {
        $this->_connection->close();
        unset($this->_connection);
    }
     
    }
 
}//end of class


$database = new MySQLDatabase();


?>

Link to comment
https://forums.phpfreaks.com/topic/283327-using-affected_rows-oop-style/
Share on other sites

$database is an instance of your database class. $database is not an instance of the mysqli database class. the instance of your database class only holds an instance of the mysqli database class in the _connection private property.

 

for the affected_rows() method, it must have the actual database connection as part of it. the only place your actual mysqli database instance/connection is at is in the _connection private property in the instance or your database class.

 

the code that runs must eventually result in $this->_connection->affected_rows. to do that, you must provide a method in your database class.

 

your current code of return $result->affected_rows == 1 ? true : false; won't work correctly. $result is either a true or a false for an UPDATE query and that code should be producing a Notice: message about trying to get a property of a non-object.

 

you need to stop using the global keyword to being the instance of your database class it into your other classes. didn't you fix this by brining it into the classes as a call time parameter when you created the instance of your classes?

You could create some additional methods in your database class...


class myDatabaseClass {

    public function query($columns, $table_name, $where = null){

    }
     
    public function update($columns, $table_name, $where = null){
         $list = array();
         foreach($columns as $col=>$val) $list[] = $col . '=' . $this->_connection->real_escape_string($val);

         $sql  = 'UPDATE ' . $table_name . ' ' . implode(',', $list) . ' ' . $where;

         if($this->_connection->query($sql) === false) return false;
         else return $this->_connection->affected_rows;

    }
}
Edited by objnoob

mac_gyver.

 

Thanks for the reply. I changed the code by adding the following method in my database class

    public function affected_rows() {
        return $this->_connection->affected_rows;
    }

 Then I changed the following on my other class that has the update method

    public function affected_rows() {
        return $this->_connection->affected_rows;
    }

Does this looks correct?

 

 

Also I don't know what you mean by "didn't you fix this by brining it into the classes as a call time parameter when you created the instance of your classes?"

 

Please explain. Thanks

Adding this method to your custom Database class is silly.

public function affected_rows() {
     return $this->_connection->affected_rows;
}

If your custom database class had query, update, delete methods. The update and delete methods would return the affected rows count, otherwise false. 

This kills two birds with 1 stone!  See this example:

class myDatabaseClass {
    
    public $this->_connection;

    public function __construct(mysqli $database){
       $this->_connection = $database;
    }

    public function update($columns, $table_name, $where = null){
         $list = array();
         foreach($columns as $col=>$val) $list[] = $col . '=\'' . $this->_connection->real_escape_string($val) . '\'';

         $sql  = 'UPDATE ' . $table_name . ' ' . implode(',', $list) . ' ' . $where;

         if($this->_connection->query($sql) === false) return false;
         else return $this->_connection->affected_rows;

    }
}
Edited by objnoob

mac_gyver.

 

Thanks for the reply. I changed the code by adding the following method in my database class

 

public function affected_rows() {
        return $this->_connection->affected_rows;
    }
 Then I changed the following on my other class that has the update method

public function affected_rows() {
        return $this->_connection->affected_rows;
    }
Does this looks correct?

 

 

Also I don't know what you mean by "didn't you fix this by brining it into the classes as a call time parameter when you created the instance of your classes?"

 

Please explain. Thanks

He means that you need to remove 'global' and instead pass in the database as an argument in your constructor. More to the point, never, ever, EVER use 'global'. I know that Lynda and other tutorials use it, but it's bad practice, especially in an OOP context. You need to forget you ever saw it.

 

Lets say I want to use "dependency injection" for my MySQLDatabase class... Do i do it like this?


   
     public function __construct() {
         $database = new MySQLDatabase();
  
     }
    

 

No, you need to pass in a database object as an argument to your constructor:

 

 

class MyObject
{
    private $db;
 
    public function __construct($db)
    {
        $this->db = $db;
    }
 
    // other class stuff
}
 
$database = new MySQLDatabase();
$myObj = new MyObject($database);

 

Functions and methods have several parts to them:

 

1. Their name

2. Their argument list

3. Their return type(s)

 

Put all together, they represent that function's or method's signature.  That signature is important, because it tells you how that function/method works at a glance.  More importantly, it infers a kind of contract between it and the rest of your code.  "I will only work if you call me by name, pass in these kinds of values.  In return, I'll give you this other kind of value."  Functions/methods are supposed to be black boxes to the code that invokes them.

 

'global' breaks that contract by introducing an implicit requirement, one that doesn't follow the normal rules of scoping.  In order for a function/method with 'global' to work correctly, the code that invokes the function/method needs to know of that hidden requirement.  That makes them not black boxes, and instead leads to hard-to-change spaghetti code.  Since functions and, even more to the point, OOP are all about reusability and modularity, you're writing code that undoes the entire point of it all.

 

So, 'global' is bad no matter how you slice it.  Any resource that uses 'global' in its code should be considered a bad resource.

 

---

 

With dependency injection, you're simply composing objects at construction time (usually).  If an object requires another object to work, simply make that dependency a member of the object that uses it.  You get all the benefits and none of the restrictions of inheritance or (even worse) singletons (which are a special form of globals, and should be avoided at all costs).  Your code will be easier to maintain.

  • 2 weeks later...
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.