用。net開發已經很多年了,最近接觸到php,發現php也很好玩。不過發現它里面沒有集合Collection類,只有數組,並且數組很強。這里我用數組來包裝成一個集合Collection,代碼如下:
class Collection{
private $_members=array();
public function addItem($obj,$key=null)
{
if($key)
{
if(isset($this->_members[$key]))
{
throw new exception("Key \"$key\" already in use!");
}
else
{
$this->_members[$key]=$obj;
}
}
else
{
$this->_members[]=$obj;
}
}
public function removeItem($key)
{
if(isset($this->_members[$key]))
{
unset($this->_members[$key]);
}
else
{
throw new exception("Invalid Key \"$key\"!");
}
}
public function getItem($key)
{
if(isset($this->_members[$key]))
{
return $this->_members[$key];
}
else
{
throw new exception("Invalid Key \"$key\"!");
}
}
public function Keys()
{
return array_keys($this->_members);
}
public function legth()
{
return sizeof($this->_members);
}
public function exists($key)
{
return (isset($this->_members[$key]));
}
}
現在我們來測試一下這個集合是否好用。
我們首先建立一個集合元素類Course:
class Course
{
private $_id;
private $_courseCode;
private $_name;
public function __construct($id,$courseCode,$name)
{
$this->_id=$id;
$this->_courseCode=$courseCode;
$this->_name=$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;
}
}
測試代碼如下:
$courses=new Collection();
$courses->addItem(new Course(1, "001", "語文"),1);
$courses->addItem(new Course(2, "002", "數學"),2);
$obj=$courses->getItem(1);
print $obj;
我想這個集合類應該可以滿足我們平日開發的需求了吧。
可是我們現在。net里面有個對象延遲加載,舉個例子來說吧,假如現在有Student這個對象,它應該有很多Course,但是我們希望在訪問Course之前Course是不會加載的。也就是說在實例化Student的時候Course個數為0,當我們需要Course的時候它才真正從數據庫讀取相應數據。就是需要我們把Collection做成惰性實例化。
修改后的Collection代碼如下:
class Collection { private $_members = array(); //collection members private $_onload; //holder for callback function private $_isLoaded = false; //flag that indicates whether the callback //has been invoked public function addItem($obj, $key = null) { $this->_checkCallback(); //_checkCallback is defined a little later 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 keys() { $this->_checkCallback(); return array_keys($this->_members); } public function length() { $this->_checkCallback(); return sizeof($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 a * 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); } } }
所需的Student如下:
class CourseCollection extends Collection {
public function addItem(Course $obj,$key=null) {
parent::addItem($obj,$key);
}
}
class Student{
private $_id;
private $_name;
public $course;
public function __construct($id,$name)
{
$this->_id=$id;
$this->_name=$name;
$this->course=new CourseCollection();
$this->course->setLoadCallback('loadCourses',$this);
}
public function getName()
{
return $this->_name;
}
public function getID()
{
return $this->_id;
}
public function __toString()
{
return $this->_name;
}
public function loadCourses(Collection $col)
{
$col->addItem(new Course(1, "001", "語文"),1);
$col->addItem(new Course(2, "002", "數學"),2);
}
}
調用代碼如下:
$student=new Student(1, "majiang");
print $student->getName();
print $student->course->getItem(1);
