I want to create a class of "Search" in the model (MVC / framework), I want to know how the method should be structured.
There are two type of search and the SQL query contain a few JOIN.
This will allow customer to type postcode, company name or city from ONE search text box:
SELECT * FROM Shop as S
JOIN shop_options as O on O.ShopID = S.ShopID
JOIN shop_openhours as OH on OH.ShopID = S.ShopID
WHERE (O.postcode = :postcode OR S.company LIKE :companyName OR S.city = :townName)
If customer visit specific town by url, eg: /town/London
Then the query would look like this:
SELECT * FROM Shop as S
JOIN shop_options as O on O.ShopID = S.ShopID
JOIN shop_openhours as OH on OH.ShopID = S.ShopID
WHERE S.city = :townName
The data will need to be manipulate in the model to find out if the shop is open or closed.
Here the quick design I come up with:
class modelSearch extends Model {
public $id;
public $shopName;
public $isOpen = false;
public static function findAll($searchType) {
$SQL = "SELECT * FROM Shop as S
JOIN shop_options as O on O.ShopID = S.ShopID
JOIN shop_openhours as OH on OH.ShopID = S.ShopID
WHERE (O.postcode = :postcode OR S.company LIKE :companyName OR S.town = :townName)";
//fetch data into $data
$search = array();
foreach ($Dbdata as $data) {
$searchModel = new modelSearch();
$searchModel->isOpen = modelSearch::isShopOpen($data['opentime'], $data['closetime']);
$searchModel->id = $data['id'];
$searchModel->shopName = $data['shopName'];
$search[] = $searchModel;
}
return $search;
}
public static function findByTown($search) {
//Same code as findAll() apart from SQL query (WHERE)
//WHERE S.town = :townName
}
public static function isShopOpen($open, $close) {
$min = ($open > 123) ? $open : 345; // Earliest allow time
if ($close < $min)
//some block code here
return true;
return false;
}
}
Im I on the right path or what can be improved?
Sorry, this is not the right way yet. Static functions are procedural code wrapped in a class. Take out all of the static and it will look a lot more like OOP, although OOP is really about the interaction of objects that you create. Calling one method after the other to achieve what you want is just a fancy way of writing functions.
Here is what I'd do:
class modelSearch extends Model {
/**** public variables should not be common in OOP. We want to control
**** the interface. Someone could change these if they were left public.
****/
private $id;
private $shopName;
private $isOpen = false;
public function __construct($shopName)
{
$this->shopName = $shopName;
}
public function findAll($searchType) {
$SQL = "SELECT * FROM Shop as S
JOIN shop_options as O on O.ShopID = S.ShopID
JOIN shop_openhours as OH on OH.ShopID = S.ShopID
WHERE (O.postcode = :postcode OR S.company LIKE :companyName OR S.town = :townName)";
/**** There is no need to instantiate any more objects in the class to
**** do the work. I am replacing the rest of your function with
**** pseudo-code.
****/
$data = execution_of_sql();
// I am not clear on what you want.
foreach ($data as $record) {
if ($this->isShopOpen($record['opentime'], $record['closetime']))
{
$openShops[] = array('id' => $record['id'],
'name' => $record['shopName']);
}
}
return $openShops;
// **** Notice how there is no need to instantiate another object
// **** because we are the object.
// $searchModel = new modelSearch();
}
// **** These could possibly be joined into 1 function with more parameters.
public function findByTown($search) {
//Same code as findAll() apart from SQL query (WHERE)
//WHERE S.town = :townName
}
// **** protected and private hide information so that you can ignore it
// **** outside the class. The interface to the class is now less
// **** cluttered.
protected function isShopOpen($open, $close) {
$min = ($open > 123) ? $open : 345; // Earliest allow time
if ($close < $min)
//some block code here
return true;
return false;
}
}
Yes,You are in the right way.Follow one MVC framework.I think you are following one frame work for this.You are created one class Search as Model and also have controller and view.