Thanks, I have taken this a bit further now including autoloading. I have also set up a base DataMapper class that the domain specific mappers extend, and this has the database connection. If I was going to build it first, where would it belong? Below is what I have so far.
index.php
<?php
use FightSportsDB\\App\\Common;
// Set up Autoloaders
require_once '../App/Common/SplClassLoader.php';
$classLoader = new Common\\SplClassLoader('FightSportsDB', '.\\..\\..');
$classLoader->register();
$doctrineClassLoader = new Common\\SplClassLoader('Doctrine', '../App/lib');
$doctrineClassLoader->register();
// Create the controller and execute the action.
$loader = new Common\\Loader($_GET);
$controller = $loader->CreateController();
$controller->ExecuteAction();
FightSportsDB\App\Common\Loader
<?php
namespace FightSportsDB\\App\\Common;
use FightSportsDB\\App\\Controller;
/**
* FightSportsDB Loader Doc Comment
*
* PHP version 5
*
* @category Application
* @package FightSportsDB
* @author Jordan Windebank
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @link http://fightsportsdb.com
*
*/
/**
* Class Loader
*
* PHP version 5
*
* @category Application
* @package FightSportsDB
* @author Jordan Windebank
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @link http://fightsportsdb.com
*/
class Loader
{
private $_controller;
private $_action;
private $_urlvalues;
/**
* Store the URL values on object creation
*
* @param array $urlvalues Input parameters
*
* @return mixed
*/
public function __construct($urlvalues)
{
$this->_urlvalues = $urlvalues;
if ($this->_urlvalues['controller'] === '' || isset($this->_urlvalues['controller']) === false) {
$this->_controller = 'Home';
} else {
$this->_controller = 'FightSportsDB\\\\App\\\\Controller\\\\'.$this->_urlvalues['controller'].'Controller';
}
if ($this->_urlvalues['action'] === '' || isset($this->_urlvalues['action']) === false) {
$this->_action = 'index';
} else {
$this->_action = $this->_urlvalues['action'];
}
}//end __construct()
/**
* Establish the requested controller as an object
*
* @return mixed
*/
public function createController()
{
// Does the class exist?
if (class_exists($this->_controller) === true) {
$parents = class_parents($this->_controller);
// Does the class extend the controller class?
if (in_array('FightSportsDB\\\\App\\\\Controller\\\\BaseController', $parents) === true) {
// Does the class contain the requested method?
if (method_exists($this->_controller, $this->_action) === true) {
return new $this->_controller($this->_action, $this->_urlvalues);
} else {
// Bad method error.
return new Controller\\ErrorController('invalidAction', $this->_urlvalues);
}
} else {
// Bad controller error.
return new Controller\\ErrorController('invalidController', $this->_urlvalues);
}
} else {
// Bad controller error.
return new Controller\\ErrorController('invalidController', $this->_urlvalues);
}
}//end createController()
}//end class
FightSportsDB\App\Controller\BaseController
<?php
namespace FightSportsDB\\App\\Controller;
abstract class BaseController
{
protected $urlvalues;
protected $action;
public function __construct($action, $urlvalues)
{
$this->action = $action;
$this->urlvalues = $urlvalues;
}//end __construct()
public function executeAction()
{
return $this->{$this->action}();
}//end executeAction()
protected function returnView($viewmodel, $fullview)
{
$className = get_class($this);
$lastNsPos = strripos($className, '\\\\');
$className = substr($className, ($lastNsPos + 1));
$className = substr($className, 0, -10);
$viewloc = '../App/View/'.$className.'/'.$this->action.'.php';
if ($fullview === true) {
include '../App/View/maintemplate.php';
} else {
include $viewloc;
}
}//end returnView()
}//end class
FightSportsDB\App\Controller\PromotionController
<?php
namespace FightSportsDB\\App\\Controller;
use FightSportsDB\\App\\Model;
class PromotionController extends BaseController
{
protected function getAll()
{
$viewmodel = new Model\\PromotionModel();
$this->ReturnView($viewmodel->getPromotions(), false);
}//end getAll()
protected function getPromotion()
{
$viewmodel = new Model\\PromotionModel();
$this->ReturnView($viewmodel->getPromotionById($this->urlvalues['id']), false);
}//end getPromotion()
}//end class
FightSportsDB\App\Model\BaseModel
<?php
namespace FightSportsDB\\App\\Model;
abstract class BaseModel
{
protected $mapper;
public function __construct()
{
}//end __construct()
}//end class
FightSportsDB\App\Model\PromotionModel
<?php
namespace FightSportsDB\\App\\Model;
use FightSportsDB\\App\\DataMapper;
class PromotionModel extends BaseModel
{
public function __construct()
{
$this->mapper = new DataMapper\\PromotionMapper();
}//end __construct()
public function getPromotions()
{
$promotions = $this->mapper->fetchAll();
return $promotions;
}//end getPromotions()
public function getPromotionByName($name)
{
$promotion = $this->mapper->fetchByName($name);
return $promotion;
}//end getPromotionByName()
public function getPromotionById($id)
{
$promotion = $this->mapper->fetchById($id);
return $promotion;
}//end getPromotionById()
}//end class
FightSportsDB\App\Model\Domain\Promotion
<?php
namespace FightSportsDB\\App\\Model\\Domain;
/**
* FightSportsDB Promotion Doc Comment
*
* PHP version 5
*
* @category Application
* @package FightSportsDB
* @author Jordan Windebank
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @link http://fightsportsdb.com
*
*/
/**
* Class Promotion
*
* PHP version 5
*
* @category Application
* @package FightSportsDB
* @author Jordan Windebank
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
* @link http://fightsportsdb.com
*/
class Promotion
{
/**
* @var int
*/
public $id;
/**
* @var string
*/
public $name;
/**
* @var string
*/
public $image;
/**
* @var string
*/
public $imageType;
/**
* Store the Promotion values on object creation
*
* @param int $promotionId Promotion ID
* @param string $promotionName Name of promotion
* @param string $image Address of promotion image
* @param string $imageType Type of promotion image [Logo|Fanart]
*/
public function __construct($promotionId, $promotionName, $image, $imageType)
{
$this->id = $promotionId;
$this->name = $promotionName;
$this->image = '../FightSportsDB/Public/images/'.$image;
$this->imageType = $imageType;
}//end __construct()
}//end class
FightSportsDB\App\Model\DataMapper
<?php
namespace FightSportsDB\\App\\DataMapper;
use Doctrine\\DBAL;
abstract class BaseMapper
{
protected $database;
public function __construct()
{
$appconfig = parse_ini_file('../App/Config/fightsportsdb.cfg');
$config = new DBAL\\Configuration();
$connectionParams = array(
'dbname' => $appconfig['dbname'],
'user' => $appconfig['user'],
'password' => $appconfig['password'],
'host' => $appconfig['host'],
'driver' => $appconfig['driver'],
);
$this->database = DBAL\\DriverManager::getConnection($connectionParams, $config);
}//end __construct()
}//end class
FightSportsDB\App\Model\PromotionMapper
<?php
namespace FightSportsDB\\App\\DataMapper;
use FightSportsDB\\App\\Model\\Domain;
class PromotionMapper extends BaseMapper
{
public function fetchAll()
{
$sql = "SELECT
p.promotionId AS 'id',
p.promotionName AS 'name',
a.artworkPath As 'image',
aType.artworkType As 'imageType'
FROM
Promotions As p
INNER JOIN PromotionsArtwork As pa ON p.promotionId = pa.promotionId
INNER JOIN Artwork As a ON pa.artworkId = a.artworkId
INNER JOIN ArtworkTypes As aType ON pa.artworkTypeId = aType.artworkTypeId";
$stmt = $this->database->query($sql);
$promotions = array();
while ($row = $stmt->fetch()) {
$promotion = new Domain\\Promotion($row['id'], $row['name'], $row['image'], $row['imageType']);
array_push($promotions, $promotion);
}
return $promotions;
}//end fetchAll()
public function fetchByName($name)
{
$sql = 'SELECT * FROM Promotions WHERE promotionName = '.$name;
$stmt = $this->database->query($sql);
$row = $stmt->fetch();
$promotion = new Domain\\Promotion($row['id'], $row['name'], $row['image'], $row['imageType']);
return $promotion;
}//end fetchByName()
public function fetchById($id)
{
$sql = 'SELECT * FROM Promotions WHERE promotionId = '.$id;
$stmt = $this->database->query($sql);
$row = $stmt->fetch();
$promotion = new Domain\\Promotion($row['id'], $row['name'], $row['image'], $row['imageType']);
return $promotion;
}//end fetchById()
}//end class
Now this is working as I expected it to (though some sections are clearly unfinished), and seems as though it would be fairly easy to build out the rest of my controllers/models in the same way. Is there anything I am doing fundamentally wrong?
My next major stumbling block is my view.
Question 3: How do I build out my view capability to allow me to load multiple sections of data on a single page?
I will end up with individual controllers/models to handle promotions, events, matches & competitors and would want to bring them all in one the main landing page. I have looked at the Composite View pattern but am having trouble finding any material online that is easy to understand how to implement. Should I set up a HomeController that gets data from multiple models (the model) and have a single view to inject it all in to?
Thanks again, this has been an excellent learning exercise so far.