I am sorry about the amount of code here. I have tried to show enough for understanding while avoiding confusion (I hope). I have included a second copy of the code at Pastebin. (The code does execute without error/notice/warning.)
I am currently creating a Content Management System while trying to implement the idea of Model View Controller. I have only recently come across the concept of MVC (within the last week) and trying to implement this into my current project.
One of the features of the CMS is dynamic/customisable menu areas and each feature will be represented by a controller. Therefore there will be multiple versions of the Controller Class, each with specific extended functionality.
I have looked at a number of tutorials and read some open source solutions to the MVC Framework. I am now trying to create a lightweight solution for my specific requirements. I am not interested in backwards compatibility, I am using PHP 5.3. An advantage of the Base class is not having to use global and can directly access any loaded class using $this->Obj['ClassName']->property/function();.
Hoping to get some feedback using the basic structure outlined (with performance in mind). Specifically;
a) Have I understood/implemented the concept of MVC correctly?
b) Have I understood/implemented Object Orientated techniques with PHP 5 correctly?
c) Should the class propertise of Base be static?
d) Improvements?
Thank you very much in advance!
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
/* A "Super Class" that creates instances */
class Base {
public static $Obj = array(); // Not sure this is the correct use of the "static" keyword?
public static $var;
static public function load_class($directory, $class)
{
echo count(self::$Obj)."\n"; // This does show the array is getting updated and not creating a new array :)
if (!in_array($class, self::$Obj)) //dont want to load it twice
{
/* Locate and include the class file based upon name ($class) */
return self::$Obj[$class] = new $class();
}
return TRUE;
}
}
/* Loads general configuration objects into the "Super Class" */
class Libraries extends Base {
public function __construct(){
$this->load_class('library', 'Database');
$this->load_class('library', 'Session');
self::$var = 'Hello World!'; //testing visibility
/* Other general funciton classes */
}
}
class Database extends Base {
/* Connects to the the database and executes all queries */
public function query(){}
}
class Session extends Base {
/* Implements Sessions in database (read/write) */
}
/* General functionality of controllers */
abstract class Controller extends Base {
protected function load_model($class, $method) {
/* Locate and include the model file */
$this->load_class('model', $class);
call_user_func(array(self::$Obj[$class], $method));
}
protected function load_view($name) {
/* Locate and include the view file */
#include('views/'.$name.'.php');
}
}
abstract class View extends Base { /* ... */ }
abstract class Model extends Base { /* ... */ }
class News extends Controller {
public function index() {
/* Displays the 5 most recent News articles and displays with Content Area */
$this->load_model('NewsModel', 'index');
$this->load_view('news', 'index');
echo self::$var;
}
public function menu() {
/* Displays the News Title of the 5 most recent News articles and displays within the Menu Area */
$this->load_model('news/index');
$this->load_view('news/index');
}
}
class ChatBox extends Controller { /* ... */ }
/* Lots of different features extending the controller/view/model class depending upon request and layout */
class NewsModel extends Model {
public function index() {
echo self::$var;
self::$Obj['Database']->query(/*SELECT 5 most recent news articles*/);
}
public function menu() { /* ... */ }
}
$Libraries = new Libraries;
$controller = 'News'; // Would be determined from Query String
$method = 'index'; // Would be determined from Query String
$Content = $Libraries->load_class('controller', $controller); //create the controller for the specific page
if (in_array($method, get_class_methods($Content)))
{
call_user_func(array($Content, $method));
}
else
{
die('Bad Request'. $method);
}
$Content::$var = 'Goodbye World';
echo $Libraries::$var . ' - ' . $Content::$var;
?>
/* Output */
0
1
2
3
Hello World!Hello World!Goodbye World - Goodbye World
As an amateur user of PHP, i am learning PHP by reading the source code of MVC PHP Framework and articles on the web.
It appears to me that there are no (or very few) open source framework that implements the "Super class" idea, instead, they use the Autoload feature of PHP:
http://www.php.net/autoload
http://www.php.net/spl_autoload_register
Also, from what I learnt in the articles and books, it is said that the use of "Super class" is a bad practice.
I think you may try to improve the code by implementing autoloading.
You may also take a look on Kohana at www.kohanaphp.com.
The Kohana 2 series is a PHP-5 only CodeIgniter rewrite plus improvement,
while the Kohana 3 series is a brand new framework with a different architecture.
Related
I have read a lot in the past few days about domain objects, data mappers, and a bunch of other stuff I had no idea about.
I have decided to try and implement this in a bit of code I am writing (partly for learning purposes, and partly because I want to create a REALLY simplified framework to build a few projects quickly...with code that I can easily understand and modify).
After reading this and this, I was planning on creating a SINGLE data mapper, with a connection to the DB inside of it, and then use a factory to pass the data mapper into every domain object (well, the ones that would need it). I include some sample code below
class data_mapper {
private $dbh;
function __construct()
{
$this->dbh = new PDO(DB_STRING, DB_USER, DB_PASS);
}
public function createUser($data) ...
public function updateUser($user_id, $data) ...
public function createCategory($data) ...
}
class user {
private $data_mapper;
public $user_id;
public $data;
function __construct($dm)
{
$this->data_mapper = $dm;
}
function someFunction() {
/* some code */
$this->data_mapper->updateUser($user_id, $data);
/* some more code */
}
}
class factory {
private $data_mapper = null;
function __construct($dm)
{
$this->data_mapper = $dm;
}
public function create($name)
{
return new $name($this->data_mapper);
}
}
/* USAGE */
$dm = new data_mapper();
$factory = new factory($dm);
$user = $factory->create('user');
I am left with two questions:
A lot of recent examples I've looked at create a different data_mapper for each model. Should I be doing this? And if I do, wouldn't that make the factory much more complex (i.e. I would need to create single PDO object and pass that into each data mapper, and then pass the right data mapper into each model)?
If my above code exposes some flaw in the understanding of models, data mappers or anything else, please enlighten me (not really a question, i know)...
As far as I can tell, "data mapper" pattern implemented in modern frameworks in the form of prototype Model class, from which all application models are inherited.
In this prototype model you can implement CRUD methods and thus your models will possess it.
Speaking of passing pdo around, local scholars will tell you that you should pass PDO object as constructor parameter. But if you'll take a look at any modern framework - they are using some sort of singleton that contains a PDO instance
So, you want a REALLY simplified PHP framework. Data mappers sound like over-engineering.
Over the years i made a few KISS frameworks in PHP, this is what i did:
Use templates (aka view) such as Smarty. Great for outsourcing your webdesign.
Make a folder named pages (aka controller). Pages are called by index.php only.
Make a folder named models. Only models talk with your DB.
Make a index.php (aka router). Has a ?page=dog parameter.
Strict MCV (aka MVC) terminology is not the holy grail, the above is a nice implementation for a simple website/app/CMS.
The parts
/pages/page_dog.inc.php
A page loads the model(s) he needs, manipulates and shows it:
<?php if(!defined('YOURFRAMEWORK')){die('External access denied');}
// Page init
require './models/model_dog.inc.php';
$id = $_GET['id']; // todo fix injection attacks
$ModelDog = new ModelDog($DB);
// Page main
$ModelDog->Load($id);
echo $ModelDog->item['breed'];
For listings (a page where user selected the $id) you may not want seperate models representing each result. Make a lister class instead, much like the model but returning multiple items in one array. Its tempting to DRY and make the ListerDog class use the ModelDog but there is no readability gain just performance pain.
/index.php (aka router) calls a page (via require_once()) after auth and init ($DB):
<?php
define('YOURFRAMEWORK', 1); // disable "External access denied" error.
require_once('config.inc.php'); // todo have this hold the $config[] array.
$DB = #new mysqli( // or your derative, so you can log each query() call.
$config['db']['host'],
$config['db']['user'],
$config['db']['pasw'],
$config['db']['database']
);
if ($DB->connect_error) { die('db error: ' . mysqli_connect_errno()); }
// Load page requested by user. For now, its dog hardcoded.
require_once('./pages/page_dog.inc.php');
$DB->close;
/models/model_dog.inc.php (aka model) talks to the DB for you, processes and sanitizes data. I also use this put form processing functions.
<?php if(!defined('YOURFRAMEWORK')){die('External access denied');}
class ModelDog extends BaseModel {
private $tablename = 'dogs';
/**
* Load last (or specific) item.
* #param integer $id
* #return boolean Returns false when failed.
*/
public function Load($id=null) {
$query = "SELECT * FROM `".$this->tablename."` WHERE `id`='".$this->DB->Sanitize($id)."';";
// TODO .. $this->item =
}
public function ItemDefaults() {
return array(
'id' => 0,
'breed' => 'unknown',
'height' => 0
);
}
// TODO ..
}
/models/basemodel.inc.php extend every model class from something common like:
abstract class BaseModel
{
protected $item = array(); // Here is all the data!
protected $DB = null;
public function __construct($aQDB) {
parent::__construct();
$this->DB = $aDB;
$this->Reset();
}
public function Reset() {
$this->item = ItemDefaults();
}
public function Item() { return $item; }
// As seen in dog
abstract public function Load($id);
abstract public function ItemDefaults();
// But descendants (models) must also implement:
abstract public function Save($id = NULL);
abstract public function Delete($id);
// You may want to add Validate() and other internal things here.
}
All of the above is a bare-minimum version of what i build myself when i need another tiny framework. You gain more in proper subclassing than making more classes doing more things. A website is a simple thing in essence, until one overcomplicates it..
The gist / TLDR;
If you really want a REALLY simplified PHP framework, dont read to much. Just write code and you'll discover what it needs to make you work better.
I want to know if this tutorial is correctly implementing factory design pattern in PHP. Below is the actual source code.
<?php
class Automobile
{
private $vehicle_make;
private $vehicle_model;
public function __construct($make, $model)
{
$this->vehicle_make = $make;
$this->vehicle_model = $model;
}
public function get_make_and_model()
{
return $this->vehicle_make . ' ' . $this->vehicle_model;
}
}
class AutomobileFactory
{
public static function create($make, $model)
{
return new Automobile($make, $model);
}
}
// have the factory create the Automobile object
$veyron = AutomobileFactory::create('Bugatti', 'Veyron');
print_r($veyron->get_make_and_model()); // outputs "Bugatti Veyron"
According to a book "Design Patterns" by Gang of Four, applicability of factory pattern is
a class can't anticipate the class of objects it must create
a class wants its subclasses to specify the objects it creates
classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate
First point, this example actually knows what class of objects to create, which is Automobile, doesn't it?
Second point, there is no subclass. Automobile class does not inherit from AutomobileFactory. I thought AutomobileFactory should have at least one function implemented by Automobile, which deals with object creations.
Can someone clarify this? I just started learning design patterns, and every time I encounter tutorials different from others, it confuses me a lot.
I pretty much agree with what is said in Wikipedia
The creation of an object precludes its reuse without significant duplication of code.
The creation of an object requires access to information or resources that should not be contained within the composing class.
The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.
The main reason I create factories is this one I highlighted.
For example, let's imagine a real world factory with many plants throughout the country. This factory produces doors. Doors needs knobs. For logistics reasons, each one of the plants of the factory has its own knob suppliers, another completely different factory.
The production manager software of this factory will choose based on some criteria which plant will produce a lot of doors, but it does not need to know from where the knobs will come. The chosen plant will ask for its own supplier for a knob for the produced door.
However, for the client, it does not matter which plant made the door, he only cares about having his door.
Let's put this on code:
class Knob {
// something...
}
interface KnobSupplier {
public function makeKnob();
}
class SaoPauloKnobSupplier {
public function makeKnob() {
return new Knob('Knob made in São Paulo');
}
}
class NewYorkKnobSupplier {
public function makeKnob() {
return new Knob('Knob made in New York');
}
}
class Door {
public function __construct(Knob $knob) {
// something...
}
}
interface DoorFactory {
public function makeDoor();
}
class SaoPauloDoorFactory {
private $knobSupplier;
public function __construct() {
$this->knobSupplier = new SaoPauloKnobSupplier();
}
public function makeDoor() {
return new Door($this->knobSupplier->makeKnob(), "Door made in São Paulo");
}
}
class NewYorkDoorFactory {
private $knobSupplier;
public function __construct() {
$this->knobSupplier = new NewYorkKnobSupplier();
}
public function makeDoor() {
return new Door($this->knobSupplier->makeKnob(), "Door made in New York");
}
}
class ProductionManager {
private $plants = array();
// methods for adding plants, etc...
public function getDoor() {
// Somehow decides which plant will create the door.
return $plant->makeDoor();
}
}
class Client {
public function getMyDoor(ProductionManager $manager) {
return $manager->getDoor();
}
}
Using this code like:
$manager = new ProductManager();
$manager->addPlant(new SaoPauloDoorFactory());
$manager->addPlant(new NewYorkDoorFactory());
$client = new Client();
var_dump($client->getMyDoor($manager));
ProductManager does not know anything about knobs, Client does not know anything about the factory having more than one plant.
I don't really like the tutorial. As you can see in the WikiPedia page about factories ( https://en.wikipedia.org/wiki/Factory_pattern ) - it's normally done differently. The WikiPedia example does comply with the rules you mention. Check out the PHP section there.
I'm with you kidonchu, I don't really see that example as a traditional factory method pattern.
I would write your example like this (psuedo code)
<?php
abstract class CarAbstract
{
protected $_vehicleMake;
protected $_vehicleModel;
public function __construct($model)
{
$this->_vehicleModel = $model;
}
public function getMakeAndModel()
{
return $this->_vehicleMake . ' ' . $this->_vehicleModel;
}
}
class Bugatti extends CarAbstract
{
public function __construct($model)
{
parent::__construct($model);
$this->_vehicleMake = get_class($this);
}
}
class AutomobileFactory
{
public static function getInstance($make, $model)
{
if (is_file('Model/Car/' . $make . '.php')){
require_once 'Model/Car/' . $make . '.php';
$car = new $make($model);
}else{
throw new Exception('Car not found');
}
}
}
$veyron = AutomobileFactory::getInstance('Bugatti', 'Veyron');
print_r($veyron->getMakeAndModel()); // outputs "Bugatti Veyron"
There's actually a single Factory Method design pattern following the original gang of four catalog. The Abstract Factory is wholly different and is based on different structural assumptions. The Simple Factory is not a design pattern, but the what Freemans call a 'programming idiom.' The Factory method includes an abstract Creator and Product, and the Clients generally make their requests through the Creator. Specific factories are found in the ConcreteCreator(s) and the concrete products are child classes of the Product class and are instantiated by concrete creators. For a complete and simple PHP example see http://www.php5dp.com/a-simple-php-design-pattern-the-factory-method/.
So I have understood how interfaces and abstraction work in PHP, I just don't see the point for example, of having a interface if it just sets a guide and requires implemented objects to have certain methods. Especially since the interface is not even getting instantiated.
This also goes with abstraction, I just can't apply it to my code and see it as such a great thing. When I am trying to create objects on a bigger scale to interact with each other in order to figure out interfaces, each class ends up passing information back and forth, but never is the interface touched.
So what I'm asking is if you guys have any advice or links to outside sources that is good at explaining this kind of thing.
Here's one simple example. Creating interfaces and abstract classes allows you to ensure an object adhears to a common API. See the example below.
interface iCar
{
function drive();
}
abstract class Car implements iCar
{
public $make = 'Generic';
public function drive()
{
printf("I'm driving in my %s%s", $this->make, PHP_EOL);
}
}
class FordTruck extends Car
{
public $make = "Ford";
}
class Porsche extends Car
{
public $make = 'Porsche';
public function drive()
{
printf("I'm speeding around in my %s%s", $this->make, PHP_EOL);
}
}
class Yugo extends Car
{
public $make = 'Yugo';
public function drive()
{
printf("I'm pushing my %s around town%s", $this->make, PHP_EOL);
}
}
function drive(iCar $car)
{
$car->drive();
}
$car1 = new FordTruck;
$car2 = new Porsche;
$car3 = new Yugo;
drive($car1);
drive($car2);
drive($car3);
Even if you don't specify the type of input parameter on the drive() function, you can check if the input is an instanceof an iCar
function drive($car)
{
if ($car instanceof iCar)
$car->drive();
}
Another example would be building a caching interface in your application. You can specify that all cache engines support the same methods for reading/writing/invalidating objects in the cache without knowing (or caring) about the actual implementation of a particular cache engine.
I could give you the simplest as possible example.
Assume you want a feature that allow your site to login with Facebook/Twitter
# here's your interface/abstract class
interface Auth_Adapter {
public function auth();
}
# now your Facebook
class Auth_Adapter_Facebook implements Auth_Adapter {
public function login() {
# include facebook-sdk and auth
}
}
# Twitter
class Auth_Adapter_Twitter implements Auth_Adapter {
public function login() {
# include twitter-oauth and auth
}
}
Imagine when someone try to use Facebook/Twitter thing They can simply call
$adapter = new Auth_Adapter_Facebook;
$adapter->login();
$adapter = new Auth_Adapter_Twitter;
$adapter->login();
As you can see both adapters use the same login interface. What's happen if in the future you have to include 'Pinterest' login? Your code still work as long as you implement the same interface.
EDIT: More explanations
Here's the reason why you have to use interface or abstract
# I use `type-hinting` here. So I can ensure that only object that implements `Auth_Adapter` will allow. Without this implementation someone might pass some other object that doesn't have `login` method in. But in our case we don't have to worry about that.
public function perform_login(Auth_Adapter $adapter) {
$adapter->login();
}
I'm wondering if anyone could give me a suggestion for to best handle this situation:
I have several systems from which to pull data to display on a single PHP-driven website. The type of information will be the same across systems (contacts, addresses, etc) but the way I pull data (MS-SQL, XML, REST) will not.
I want to create a class, or set of classes, for each of the connection types and use simple methods such as getContact(), getAddress(), etc. I am wondering how best to structure this.
The most obvious way that comes to mind means creating classes for each connection type, like:
class.sys_mysql.php. class.sys_xml.php, etc
But then won't I be duplicating the methods in each class? Maybe that's OK, but I'm curious if there's a better way, as far as future maintenance goes.
Maybe I should simply isolate the queries/data extraction methods, into separate class files? Classes within classes? Extended classes? I'm less familiar with these.
Any advice would be greatly appreciated.
DC
--------- more info ----------
Hi all. I really appreciate all the great advice. Not to belabor this thread but I'm still a bit confused on how I should break things down. I will try and be a bit more specific:
Basically, I have 3 (more in the future) offices, from which one PHP website pulls information. Each office uses a different CRM, and a different system for interfacing with that CRM. One uses MSSQL, another XML requests, etc.
Each office wants to display information similarly on the website, but there are minor differences. There may be more differences in the future. However, there are by far more similarities, and so I want to capitalize on higher level functions like getContacts($id) which are shared between them.
I am trying to write these classes so I can:
1) use higher level methods to pull data easily
2) account for different ways of pulling data (xml,sql,etc)
3) account for differences between how data is displayed on the website (office 1, office 2, office 3)
4) manage the connection credentials for each office and allow for expandability_
5) I should also mention that I will be creating separate classes for reporting, sending out automated e-mails, calculating finances...separate modules that will need to use existing classes to pull data.
I realize that some of the examples here see to cover 1 and 2, but I am confused as to how to get 3, 4 and 5 working with 1 and 2.
I really appreciate the help.
DC
This is what Interfaces are for.
You define the methods required to interact with the data in an Interface, and then you create classes that implement that Interface
If some of the systems have similar access models (i.e. perhaps two different DB Servers, but both are accessed using PDO) you could abstract it further and put the "low level" functionality into service-specific classes (which implement an Interface) and then a higher-level class which defines the actual methods you use.
Another option is that you could put the "common" methods (those that are identical or can be made idetntical with service-type checks) into a base class, which all others extend.
Example for option one:
interface DataModel {
public function findContacts($search);
public function getContact($id);
public function findAddresses($search);
public function getAddress($id);
}
class XMLDataModel implements DataModel {
public function findContacts($search) {
...
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
class RESTDataModel implements DataModel {
public function findContacts($search) {
...
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
As you can see, you simply define an Interface, which specifies which methods a class must implement.
If you had two very similar classes, perhaps one for MySQL and one for PostreSQL, and you can't/don't want to combine them into a single PDO class, you could do the following:
class PDODataModel implements DataModel {
private $model;
public function __construct ($serverType) {
if ($serverType === 'mysql') {
$this->model = new MySQLPDODataModel();
}
elseif ($serverType === 'postgresql') {
$this->model = new PostgresQLPDODataModel();
}
}
public function findContacts($search) {
// common logic about $search, perhaps checking it's a valid search?
$result = $this->model->searchForContacts($search);
// more common logic, maybe higher level filtering..
return $result;
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
interface PDODataModelDriver {
public function searchForContacts($search);
}
class MySQLPDODataModel extends PDODataModel implements PDODataModelDriver {
public function searchForContacts($search) {
// MySQL-specific query to search for contacts
}
}
class PostgresSQLPDODataModel extends PDODataModel implements PDODataModelDriver {
public function searchForContacts($search) {
// PostgreSQL-specific query to search for contacts
}
}
The other option I mentioned was to work in the opposite direction:
abstract class PDODataModel implements DataModel {
protected $pdo;
protected $dsn;
public function __construct () {
$this->pdo = new PDO($this->dsn);
}
public function findContacts($search) {
// common logic about $search, perhaps checking it's a valid search?
$result = $this->searchForContacts($search);
// more common logic, maybe higher level filtering..
return $result;
}
public function getContact($id) {
...
}
public function findAddresses($search) {
...
}
public function getAddress($id) {
...
}
}
class MySQLPDODataModel extends PDODataModel {
protected $dsn = 'mysql:dbname=testdb;host=127.0.0.1';
protected function searchForContacts($search) {
// MySQL-specific query to search for contacts
}
}
class PostgresSQLPDODataModel extends PDODataModel {
protected $dsn = 'pgsql:host=localhost;port=5432;dbname=testdb';
protected function searchForContacts($search) {
// PostgreSQL-specific query to search for contacts
}
}
This is a classical example of a strategy design patter. Your first mind was absolutely fine, but if you're repeating yourself in each class you should consider creation of a abstract class that will handle the common code.
So it could look like this:
$myService = new MyService(new XMLReader('/path/to/file'));
echo $myService->getContanct('abc')->getName();
And skeleton of your classes:
class MyService {
private $reader;
public function __construct(ReaderInterface $reader) {
$this->reader = $reader;
}
// ...
public function getContacnt($id) {
$contact = $this->reader->getContact($id);
// do some extra stuff here
return $contact;
}
}
interface ReaderInterface {
public function getContanct($id);
public function getAddress($id);
}
abstract class AbstractReader implements ReaderInterface {
protected $loaded = false;
protected $data = array();
abstract protected function load();
public function getContanct($id) {
if ($this->loaded == false) {
$this->load();
$this->loaded = true;
}
return $this->data['contact'][$id];
}
}
class XMLReader extends AbstractReader {
public function __construct($filepath) {
...
}
protected function load() {
...
foreach (...) {
$this->data[...] = ...;
}
}
}
class MSSQLReader extends AbstractReader {
public function __construct(PDO $dbh) {
...
}
protected function load() {
...
while ($row = $stmt->fetchRow()) {
$this->data[...] = ...;
}
}
}
EDIT (2011-03-07) - According to your comment.
PHP supports variable variables (new $type()) but never use this! It's a horrible, and if overused make code really crappy.
This is a yet another example of a "classical issue". Use a factory pattern (depending on the complexion of the creation you might want to use more abstract variety of this pattern - abstract factory
When you need to dynamically determine class name (eg. from variable) use reflection API to instate an object.
You should create an object-storage mapping layer for each data source, which instantiates the objects into storage agnostic model objects. See http://martinfowler.com/eaaCatalog/dataMapper.html
If you have control over the structure of your data formats, I suggest you serialize your data in a consistent way (especially in XML) and provide drivers for each data format.
For instance, every driver will have 'findAll', 'getOne', 'count', etc. methods. The driver can be given a model to populate with the retrieved data.
abstract class DataDriver {
function __construct($model) {}
abstract public function findAll();
abstract public function getOne();
abstract public function count();
// ...
}
class XMLDriver extends DataDriver {
// implements all the methods
}
class SQLDriver extends DataDriver {
// implements all the methods
}
class Contact {
public var $firstName;
public var $lastName;
function getFullName() {
return trim($this->firstName . ' ' . $this->lastName);
}
}
$accessor = new SQLDriver('Contact');
$contacts = $accessor->findAll();
If your data will be serialized in an uncontrolled manner, the approach you suggest is the best. Just make sure to separate your models (e.g. Address book, Contact) from the method of retrieval (eg. get_address_book_xml, get_address_book_sql, etc.)
Of course there are many ways of separating your models from your data-mapping driver. The importance is you find the solution that works best for you given that you're using such different formats.
I use zend framework and I would like to have your advice to modelize my classes.
I have 3 classes Patrimony.php Project.php and Version.php.
Version extends Project extends Patrmimony.
In other hand I have a folder structure like this /data/patrimonies/projects/versions/
I don't know if I have to use a Design Pattern or something like that, if patrimony have a variable $_project which contains an instance of project, how do I instanciate my class (__construct() params). In brief I am very confusing with OOP.
Please light me :-)
class Admin_Model_Patrimony
{
}
class Admin_Model_Project extends Admin_Model_Patrimony
{
}
class Admin_Model_Version extends Admin_Model_Project
{
}
I have look to the composition pattern and it seems it is interessant when you want to compose with different number of leaves. In my case There are always one patrimony one project and one version for any entities.
My goal is sometimes I just use informations about a patrimony othertimes I only needs information about project.
I show you how I have design my classes, see the last lines for execution process and expected values.
I think this code doesn't work so how do I do to set variable of the parents when I instanciate a child?
// Version
class Version extends Project
private $this->_patId;
private $this->_proId;
private $this->_verId;
{
public function __contruct($patrimonyId, $projectId, $versionId)
{
$this->_patId = $patrimonyId;
$this->_proId = $projectId;
$this->_verId = $versionId;
}
public function getVersionId()
{
return $this->_verId;
}
// Project
class Project extends Patrimony
private $this->_patId;
private $this->_proId;
{
public function __contruct($patrimonyId, $projectId)
{
$this->_patId = $patrimonyId;
$this->_proId = $projectId;
}
public function getProjectId()
{
return $this->_proId;
}
// Patrimony
class Patrimony
private $this->_patId;
{
public function __contruct($patrimonyId)
{
$this->_patId = $patrimonyId;
}
public function getPatrimonyId()
{
return $this->_patId;
}
// Execution
$version = new Version(1,2,3);
$version->getVersionId(); // should return 1
$version->getProjectId(); // should return 2
$version->getPatrimonyId(); // should return 3