Jump to content

Question about instantiating


Go to solution Solved by kicken,

Recommended Posts

Hey,

 

I was going through a PHP coding tutorial. And in this tutorial it seemed like the $photo variable is an instance variable, but I can't seem to find how it was instantiated?? Can anyone please help me. Below is the code

<?php require_once("../../includes/initialize.php"); ?>
<?php if (!$session->is_logged_in()) { redirect_to("login.php"); } ?>
<?php
  // Find all the photos
  $photos = Photograph::find_all();
?>
<?php include_layout_template('admin_header.php'); ?>

<h2>Photographs</h2>

<table class="bordered">
  <tr>
    <th>Image</th>
    <th>Filename</th>
    <th>Caption</th>
    <th>Size</th>
    <th>Type</th>
  </tr>
<?php foreach($photos as $photo): ?>
  <tr>
    <td><img src="../<?php echo $photo->image_path(); ?>" width="100" /></td>
    <td><?php echo $photo->filename; ?></td>
    <td><?php echo $photo->caption; ?></td>
    <td><?php echo $photo->size_as_text(); ?></td>
    <td><?php echo $photo->type; ?></td>
  </tr>
<?php endforeach; ?>
</table>
<br />
<a href="photo_upload.php">Upload a new photograph</a>

<?php include_layout_template('admin_footer.php'); ?>

Link to comment
https://forums.phpfreaks.com/topic/277474-question-about-instantiating/
Share on other sites

I'm sorry, I am really confused on how this works. In the coding tutorial blow there is a variable that is assigned to a satic call..  $photos = Photograph::find_all()

and then it runs a foreach loop on the array that it returns

 

"<?php foreach ($photos as $photo) { ?>"

 

Trq said that "Photograph::find_all() returns an array of object"  However there are methods that I called in the object with the $photo-> variable that find_all() didn't return.

Like for example I created a test() method and called it with the $photo variable $photo->test() and it still worked? So i am confused of how did that work when that static call Photograph::find_all() didn't call it

 

Below is my photograph class

<?php 
require_once(LIB_PATH.DS.'database.php');
 
 class Photograph {
	 
protected static $table_name="photographs";
 protected static $db_fields=array('id', 'filename', 'type', 'size', 'caption');
public  $id;
	public  $filename;
	public  $type;
	public  $size;
	public  $caption;
 
 private    $temp_path; 
 protected  $upload_dir="images";
 public     $errors=array();
 								
 public $upload_errors = array( 

UPLOAD_ERR_OK 	  => "No Errors.", 
UPLOAD_ERR_INI_SIZE => "Large than upload_max_filesize", 
UPLOAD_ERR_FORM_SIZE => "Larger than from MAX_FILE_SIZE", 
UPLOAD_ERR_PARTIAL => "Partial Upload", 
UPLOAD_ERR_NO_FILE => "No File", 
UPLOAD_ERR_CANT_WRITE => "Can't write to the disk",
UPLOAD_ERR_EXTENSION => "File upload stopped by extension");

//Need to enter the error checking. Last thing i did. 

// Pass in $_FILE(['uploaded_file']) as an argument
public function attach_file($file) {
	//Preform error checking on the form parameters
	//Set object attributes to the form parameters 
	//Don't worry about saving anything to the database yet
	if(!$file || empty($file) || !is_array($file)) {
		$this->errors[] = "There was no file uploaded";
		return false;
	} elseif($file['error'] != 0) {
$this->errors[] = $this->upload_errors[$file['error']];
		return false;
	} else {
	
	$this->temp_path = $file['tmp_name'];
	$this->filename = basename($file['name']);
	$this->type = $file['type'];
	$this->size = $file_size['size'];
	return true;
	}
	
}

public function save() {
if(isset($this->id)) {
			// Really just to update the caption
			$this->update();
		} else {
			// Make sure there are no errors
			
			// Can't save if there are pre-existing errors
		  if(!empty($this->errors)) { return false; }
		  
			// Make sure the caption is not too long for the DB
		  if(strlen($this->caption) > 255) {
				$this->errors[] = "The caption can only be 255 characters long.";
				return false;
			}
	
 // Can't save without filename and temp location
		  if(empty($this->filename) || empty($this->temp_path)) {
		    $this->errors[] = "The file location was not available.";
		    return false;
		  }
			
			// Determine the target_path
		  $target_path = SITE_ROOT .DS. 'public' .DS. $this->upload_dir .DS. $this->filename;
		  
		  // Make sure a file doesn't already exist in the target location
		  if(file_exists($target_path)) {
		    $this->errors[] = "The file {$this->filename} already exists.";
		    return false;
		  }
	
		// Attempt to move the file 
			if(move_uploaded_file($this->temp_path, $target_path)) {
		  	// Success
				// Save a corresponding entry to the database
				if($this->create()) {
					// We are done with temp_path, the file isn't there anymore
					unset($this->temp_path);
					return true;
				}
	} else {
	$this->errors[] = "The file upload faled, possibly due to incorrect permessions on the upload folder";	
	}
	
	
}
}

public function image_path() {
return $this->upload_dir.DS.$this->filename;	
}

public function size_as_text() {
if($this->size < 1024) {
return "{$this->size} bytes";	
} elseif($this->size < 1048576) {
$size_kb = round($this->size/1024);
return "{size_kb} KB";	
} 
	
}


public function test() {
echo "This is a test";	
}

 
 
 
 //Common datavase bethod
 
 public static function find_all() {
		return self::find_by_sql("SELECT * FROM ".self::$table_name);
  }
  
  public  function find_by_id($id=0)  { // Takes an ID as an argument
    $result_array = self::find_by_sql("SELECT * FROM ".self::$table_name." WHERE id={$id} LIMIT 1"); 
		return !empty($result_array) ? array_shift($result_array): false;
  }
  
  public static function find_by_sql($sql="") {
    global $database; // Brings in the $database instanitated object. 
    $result_set = $database->query($sql); // Runs the query on the $sql argument
    $object_array = array(); // Initilizes an object_array
    while ($row = $database->fetch_array($result_set)) {
      $object_array[] = self::instantiate($row); // Take the inisiated row and assignes it to $object_array
    }
    return $object_array; 
  }
 
 private static function instantiate($record) {
		// Could check that $record exists and is an array
    $object = new self;
		// Simple, long-form approach:
		// $object->id 				= $record['id'];
		// $object->username 	= $record['username'];
		// $object->password 	= $record['password'];
		// $object->first_name = $record['first_name'];
		// $object->last_name 	= $record['last_name'];
		
		// More dynamic, short-form approach:
		foreach($record as $attribute=>$value){
		  if($object->has_attribute($attribute)) {
		    $object->$attribute = $value;
		  }
		}
		return $object;
	}
	
	
	private function has_attribute($attribute) {
	  // We don't care about the value, we just want to know if the key exists
	  // Will return true or false
	  return array_key_exists($attribute, $this->attributes());
	}
	
	
	
		protected function attributes() { 
		// return an array of attribute names and their values
	  $attributes = array();
	  foreach(self::$db_fields as $field) {
	    if(property_exists($this, $field)) {
	      $attributes[$field] = $this->$field;
	    }
	  }
	  return $attributes;
	}
	
	protected function sanitized_attributes() {
	  global $database;
	  $clean_attributes = array();
	  // sanitize the values before submitting
	  // Note: does not alter the actual value of each attribute
	  foreach($this->attributes() as $key => $value){
	    $clean_attributes[$key] = $database->escape_value($value);
	  }
	  return $clean_attributes;
	}
	
 
 public function create() {
global $database; 
$attriubutes = $this->sanitzed_attriubutes();
$sql = "INSERT INTO ".self::table_name." (";
$sql .= join(", ", array_keys($attriubutes));
$sql .= ") VALUES ('";
$sql .= join(", ", array_values($attriubutes));
$sql .= "')";
if($database->query($sql)) {
$this->id = $database->insert_id();
return true; 	
	
} else {
	
	return false;
}
   
   
   
   }
  
 public function update() {
	global $database; 
	$attributes = $this->sanitzed_attriubutes(); // First we assign the attributes() functions to the $attriubutes variable. 
    //Then we run a foreach on the attriubutes
	foreach ($attributes as $key=>$value) {
	   	$attribute_pairs[] = "{$key}='{$value}'";
	}
	
	$sql = "UPDATE ".self::table_name." SET ";
	$sql .= join(", ", $attribute_pairs);
	$sql .= " WHERE id=" . $this->id; 
	$database->query($sql);
	return ($database->affected_rows() == 1) ? true : false;
	
	
   }
   
 public function delete() {
   global $database;
	$sql = "DELETE FROM ".self::table_name. " WHERE id=". $this->id . " LIMIT 1";
	$database->query($sql);
	return ($database->affected_rows() == 1) ? true : false; 
	 
   }
   
 
 
 }

?>

and below is where I do all my calling

<?php 

require_once("../../includes/initialize.php");
if(!$session->is_logged_in()) { redirect_to("login.php"); }

$photos = Photograph::find_all();

include_layout_template('admin_header.php');


?>

<h2> Photographs </h2>

<table class="borderd"> 
<tr>
<th>Image </th>
<th> Filename </th>
<th> Caption </th>
<th> Size </th>
<th> Type </th>
<th> Test </th>

</tr>

<?php foreach ($photos as $photo) { ?>
<td> <img src="../<?php echo $photo->image_path(); ?>"  width="100"/>  </td> 
<td> <?php echo $photo->filename; ?> </td>
<td> <?php echo $photo->caption; ?> </td>
<td> <?php echo $photo->size > 1024 ? round($photo->size / 1024) . "KB" : $photo->size . "Bytes"; ?> </td>
<td> <?php echo $photo->type; ?> </td>
<td> <?php  $photo->test(); // How is test() being called ?> </td>
	
<?php } ?>
</table>


<?php include_layout_template('admin_footer.php'); ?>

the objects that are in the array are instances of your Photograph class, one for each row that the query matches, with the properties set to whatever data is in the row from the query, and whatever methods your class has.

Edited by mac_gyver

the objects that are in the array are instances of your Photograph class, one for each row that the query matches, with the properties set to whatever data is in the row from the query, and whatever methods your class has.

 

Hey. I trying to understand but still can't figure it out. What do you mean by "one for each row that the query matches, with the properties set to whatever data is in the row from the query, and whatever methods your class has.?

 

"

if you mean, how did i determine what it is doing, i traced through the execution path and read the code -

 

$photos = Photograph::find_all();

//////////////////////////////////////////////////////////

 public static function find_all() {
        return self::find_by_sql("SELECT * FROM ".self::$table_name);
  }
 
/////////////////////////////////////////////////////////

  public static function find_by_sql($sql="") {
    global $database; // Brings in the $database instanitated object.
    $result_set = $database->query($sql); // Runs the query on the $sql argument
    $object_array = array(); // Initilizes an object_array
    while ($row = $database->fetch_array($result_set)) {
      $object_array[] = self::instantiate($row); // Take the inisiated row and assignes it to $object_array
    }
    return $object_array;
  }

//////////////////////////////////////////////////////////

 private static function instantiate($record) {
        // Could check that $record exists and is an array
    $object = new self;
        // Simple, long-form approach:
        // $object->id                 = $record['id'];
        // $object->username     = $record['username'];
        // $object->password     = $record['password'];
        // $object->first_name = $record['first_name'];
        // $object->last_name     = $record['last_name'];
        
        // More dynamic, short-form approach:
        foreach($record as $attribute=>$value){
          if($object->has_attribute($attribute)) {
            $object->$attribute = $value;
          }
        }
        return $object;
    }

 

//////////////////////////////////////////////////////////

 

    private function has_attribute($attribute) {
      // We don't care about the value, we just want to know if the key exists
      // Will return true or false
      return array_key_exists($attribute, $this->attributes());
    }

 

 

 
if you mean, what does that mean, the answer's in your code and would require that you understand what each statement in your code is doing. do you have a specific question about what any of your code is doing?

if you mean, how did i determine what it is doing, i traced through the execution path and read the code -

 

 

 

if you mean, what does that mean, the answer's in your code and would require that you understand what each statement in your code is doing. do you have a specific question about what any of your code is doing?

 

I don't understand how does  find_all() function call all the methods in the class when its only argument is mysql query.  Isn't that supposed to select everything from the table named photograph?

  • Solution

I don't understand how does  find_all() function call all the methods in the class when its only argument is mysql query.  Isn't that supposed to select everything from the table named photograph?

Note: This is a fairly dumbed-down explanation, hopefully for easy understanding

 

The find_all method queries the database and gets back as a result an array of every row that exist in the database. For every row that it gets back from the database, it runs essentially $obj = new Photograph; and then sets all the properties in the Photograph class to the corresponding column from the database row. Each time it makes a new photograph object, it sticks the object into a array which eventually is the return value for find_all.

 

So your code gets back an array of objects, each of those objects is a new separate instance of the Photograph class.

 

Hopefully that helps explain things. If not you might need to try and read more about how classes and objects work in general.

Edited by kicken

Note: This is a fairly dumbed-down explanation, hopefully for easy understanding

 

The find_all method queries the database and gets back as a result an array of every row that exist in the database. For every row that it gets back from the database, it runs essentially $obj = new Photograph; and then sets all the properties in the Photograph class to the corresponding column from the database row. Each time it makes a new photograph object, it sticks the object into a array which eventually is the return value for find_all.

 

So your code gets back an array of objects, each of those objects is a new separate instance of the Photograph class.

 

Hopefully that helps explain things. If not you might need to try and read more about how classes and objects work in general.

 

Kicken,

 

Thanks for making it more clearer for me. After reading it I know understand what you explained.

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.