I'll provide a practical example, because it's probably easier to follow. I won't use HTML as an output format as that's too weighted in PHP and makes things less obvious.
PHP Code:
interface TomsModel {
public function getData();
}
interface TomsView {
public function output();
public function getMimeType();
}
Let's assume getData() provides a key => value array of some arbitrary data and view:
utput() returns a string and getMimeType() returns the MIME type of the data in output();
I can now define some views to display the data in a variety of formats:
PHP Code:
class JSonView implements TomsView {
private $model;
public function __construct(TomsModel $model) {
$this->model = $model;
}
public function output() {
return json_encode($this->model->getData());
}
public function getMimeType() {
return 'application/json';
}
}
class CsvView implements TomsView {
private $model;
public function __construct(TomsModel $model) {
$this->model = $model;
}
public function output() {
$stream = fopen('php://temp/');
foreach ($this->model->getData() as $row) {
fputcsv($stream, $row);
}
return stream_get_contents($stream);
}
public function getMimeType() {
return 'text/csv';
}
}
//Using the pchart library to display the data as a pie chart: http://pchart.sourceforge.net/documentation.php?topic=exemple15
class PieChartView implements TomsView {
private $model;
public function __construct(TomsModel $model) {
$this->model = $model;
}
public function output() {
$dataSet = new pData;
foreach ($this->model->getData() as $row) {
$dataSet->addPoint($row);
}
$dataSet->addAllSeries();
$chart = new pChart(300, 300);
$chart->drawBasicPieGraph($dataSet->GetData(), $dataSet->GetDataDescription(),120,100,70,PIE_PERCENTAGE,255,255,218);
return $chart->render();
}
public function getMimeType() {
return 'image/png';
}
}
The beauty of this is that these views could work with any of these models:
PHP Code:
class DatabaseModel implements TomsModel {
private $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function getData() {
return $this->pdo->query('.....');
}
}
class CSVModel implements TomsModel {
private $csvFile;
public function __construct($csvFile) {
$this->csvFile = $csvFile;
}
public function getData() {
$returnData = array();
if (($handle = fopen($this->csvFile, 'r')) !== false) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$returnData[] = $data;
}
}
fclose($handle);
return $returnData;
}
}
class SatelliteInteceptorModel implements TomsModel {
public function __construct(SatelliteStream $statelliteStream) {
$this->satelliteStream = $statelliteStream) ;
}
private function decode($data) {
//...
}
public function getData() {
$data = $this->decode($this->satelliteStream->interceptData);
//format $data into an array that the view is expecting
return $data;
}
}
Any of these models can be used with any of the views. This is where MVC shines because the data source is entirely disconnected from the display logic. The model provides the view with some data in a format they both know about. The view does whatever it likes to this data in order to display it and the model takes data from any source and puts it into the format that the view can use. This makes the display logic reusable because it can be used with any of the models and it means a new model can be added without having to write a new view for it.
For example, I could write a new model which combined data from two separate CSV files and still use the same view.
As you see, it's possible to go from CSV -> CSV using my example code and have a lot of redundant processing but, this redundancy is what allows the view to be agnostic of the data source and is a very small price to pay for having interchangeable components. Yes the view could just load the CSV directly and output it, but then its data source must always be a CSV file.
Bookmarks