AwakenedYes Posted June 3, 2011 Share Posted June 3, 2011 Trying to populate collection only as needed using callback function I am going through WROX Professional PHP5 Chapter 5 - Collections. I am trying to populate a collection from a DB (MSSQL) only as members are called, rather than populate everything, using callback functions as detailed in the book. I just can't get the result as expected, which is: "Bob Smith is currently enrolled in CS101". Hopefully the code will explain: //factoryTest.php <?php require_once 'class.Collection.php'; require_once 'class.CourseCollection.php'; require_once 'class.Course.php'; require_once 'class.Student.php'; require_once 'class.StudentFactory.php'; $studentID = 1; try { $objStudent = StudentFactory::getStudent($studentID); $objStudent2 = StudentFactory::getCoursesForStudent($studentID, $col); } catch (Exception $e) { die("Student #$studentID doesn't exist in the database!"); } print $objStudent . ($objStudent->courses->exists("CS101") ? ' is ' : ' is not '). 'currently enrolled in CS101'; //displays: "Bob Smith is enrolled in CS101" ?> //class.StudentFactory.php <?php class StudentFactory { public static function getStudent($id) { $serverName = ""; $connectionInfo = array("Database"=>"Registra"); $con = sqlsrv_connect($serverName, $connectionInfo) or die("Failure connecting to database!"); $sql = "SELECT * FROM \"student\" WHERE \"studentid\" = $id"; $result = sqlsrv_query($con, $sql); if ($result === false) { throw new Exception("Student $id does not exit."); } else { $row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC); return new Student($row['studentid'], $row['name']); } } public static function getCoursesForStudent($id, $col) { $serverName = ""; $connectionInfo = array("Database"=>"Registra"); $con = sqlsrv_connect($serverName, $connectionInfo) or die("Failure connecting to database!"); $sql = "SELECT \"course\".\"courseid\", \"course\".\"coursecode\", \"course\".\"name\" FROM \"course\" INNER JOIN \"studentcourse\" ON \"course\".\"courseid\" = \"studentcourse\".\"courseid\" INNER JOIN \"student\" ON \"studentcourse\".\"studentid\" = \"student\".\"studentid\" WHERE \"course\".\"courseid\" = \"studentcourse\".\"courseid\" AND \"studentcourse\".\"studentid\" = $id"; $res = sqlsrv_query($con, $sql); if (sqlsrv_has_rows($res)) { $rowCount = sqlsrv_num_rows($res); while ($row = sqlsrv_fetch_array($res, SQLSRV_FETCH_ASSOC)) { $objCourse = new Course($row['courseid'], $row['coursecode'], $row['name']); $col->addItem($objCourse, $objCourse->getCourseCode()); // echo $row['courseid']." ".$row['coursecode']." ".$row['name']; } return $col; } } } ?> //class.Student.php <?php class Student { private $_id; private $_name; public $courses; public function __construct($id, $name) { $this->_id = $id; $this->_name = $name; $this->courses = new CourseCollection(); $this->courses->setLoadCallback('_loadCourses', $this); } public function getName() { return $this->_name; } public function getID() { return $this->_id; } public function _loadCourses(CourseCollection $col) { $courses = StudentFactory::getCoursesForStudent($this->_id, $col); } public function __toString() { return $this->_name; } } ?> //class.CourseCollection.php <?php class CourseCollection extends Collection { public function addItem(Course $obj, $key = null) { parent::addItem($obj, $key); } } ?> //class.Course.php <?php class Course { private $_id; private $_courseCode; private $_name; public function __construct($id, $courseCode, $name) { $this->_id = $id; $this->_courseCode; $this->_name; } public function getName() { return $this->_name; } public function getID() { return $this->_id; } public function getCourseCode() { return $this->_courseCode; } public function __toString() { return $this->_name; } } ?> //class.Collection.php <?php class Collection { private $_members = array(); // Collection members. private $_onload; // Holder for callback function private $_isLoaded = false; // Flag that indicates whether the // has been invoked. public function addItem($obj, $key = null) { $this->_checkCallback(); if ($key) { if (isset($this->_members[$key])) { throw new KeyInUseException("Key \"$key\" already in use!"); } else { $this->_members[$key] = $obj; } } else { $this->_members[] = $obj; } } public function removeItem($key) { $this->_checkCallback(); if (isset($this->_members[$key])) { unset($this->_members[$key]); } else { throw new KeyInvalidException("Invalid key \"$key\"!"); } } public function getItem($key) { $this->_checkCallback(); if (isset($this->_members[$key])) { return $this->_members[$key]; } else { throw new KeyInvalidException("Invalid key \"$key\"!"); } } public function length() { $this->_checkCallback(); return sizeof($this->_members); } public function keys() { $this->_checkCallback(); return array_keys($this->_members); } public function exists($key) { $this->_checkCallback(); return (isset($this->_members[$key])); } /** * Use this method to define a function to be invoked prior to accessing the * collection. The function should take a collection as its sole parameter. */ public function setLoadCallback($functionName, $objOrClass = null) { if ($objOrClass) { $callback = array($objOrClass, $functionName); } else { $callback = $functionName; } // Make sure the function/method is valid. if (! is_callable($callback, false, $callableName)) { throw new Exception("$callableName is not callable as a " . "parameter to onload"); return false; } $this->_onload = $callback; } /** * Check to see if a callback has been defined and if so, * whether or not it has already been called. If not, * invoke the callback function. */ private function _checkCallback() { if (isset($this->_onload) && ! $this->_isLoaded) { $this->_isLoaded = true; call_user_func($this->_onload, $this); } } } class KeyInvalidException extends Exception {} class KeyInUseException extends Exception {} ?> I always get "Bob Smith is not currently enrolled in CS101". Even in a foreach loop: foreach ($objStudent->courses as $objCourse) { print $objCourse->getCourseCode." - ".$objCourse->getName" } I don't get anything. What am I doing wrong? What am I missing? Is it going out of scope? The DB is connecting and returning correctly! Hope you can help - cheers Quote Link to comment https://forums.phpfreaks.com/topic/238348-trying-to-populate-collection-only-as-needed-using-callback-function/ Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.