當您希望以不同的方式處理(篩選、排序等)相同的數據時,Traits 對於策略很有用。
舉例來說,您有一個產品列表,您想根據某些條件(品牌、規格等)篩選,或依不同方式(價格、標籤等)排序。您可以建立一個排序 trait,其中包含針對不同排序類型(數值、字串、日期等)的不同函式。然後,您不僅可以在您的產品類別中使用此 trait(如範例所示),也可以在其他需要類似策略的類別中使用(例如對某些資料應用數值排序)。
<?php
trait SortStrategy {
private $sort_field = null;
private function string_asc($item1, $item2) {
return strnatcmp($item1[$this->sort_field], $item2[$this->sort_field]);
}
private function string_desc($item1, $item2) {
return strnatcmp($item2[$this->sort_field], $item1[$this->sort_field]);
}
private function num_asc($item1, $item2) {
if ($item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
return ($item1[$this->sort_field] < $item2[$this->sort_field] ? -1 : 1 );
}
private function num_desc($item1, $item2) {
if ($item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
return ($item1[$this->sort_field] > $item2[$this->sort_field] ? -1 : 1 );
}
private function date_asc($item1, $item2) {
$date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
$date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
if ($date1 == $date2) return 0;
return ($date1 < $date2 ? -1 : 1 );
}
private function date_desc($item1, $item2) {
$date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
$date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
if ($date1 == $date2) return 0;
return ($date1 > $date2 ? -1 : 1 );
}
}
class Product {
public $data = array();
use SortStrategy;
public function get() {
$this->data = array(
101222 => array('label' => '超讚產品', 'price' => 10.50, 'date_added' => '2012-02-01'),
101232 => array('label' => '沒那麼讚的產品', 'price' => 5.20, 'date_added' => '2012-03-20'),
101241 => array('label' => '蠻棒的產品', 'price' => 9.65, 'date_added' => '2012-04-15'),
101256 => array('label' => '超酷的產品', 'price' => 12.55, 'date_added' => '2012-01-11'),
101219 => array('label' => '普通產品', 'price' => 3.69, 'date_added' => '2012-06-11'),
);
}
public function sort_by($by = 'price', $type = 'asc') {
if (!preg_match('/^(asc|desc)$/', $type)) $type = 'asc';
switch ($by) {
case 'name':
$this->sort_field = 'label';
uasort($this->data, array('Product', 'string_'.$type));
break;
case 'date':
$this->sort_field = 'date_added';
uasort($this->data, array('Product', 'date_'.$type));
break;
default:
$this->sort_field = 'price';
uasort($this->data, array('Product', 'num_'.$type));
}
}
}
$product = new Product();
$product->get();
$product->sort_by('name');
echo '<pre>'.print_r($product->data, true).'</pre>';
?>