Jag håller på med en sida och har nu stött på ett problem.
Har gjort en fil som hämtar nyheter från en databas.
Filen lägger all data i en array, som sedan presenteras på "huvudsidan".
Jag inkluderar den här filen med require.
Nu ska jag visa en annan typ av nyheter på ett annat ställe på samma sida och vill använda samma fil (module.news.php) fast skicka med ett annat "WHERE..." statement.
Kan man köra "unset" eller nått liknande för att döda min require, eller går det att lösa samma sak på ett bättre sätt, genom t.ex. en funktion, eller klass?
Tanken är att scriptet i filen ska kunna användas på flera ställen på sidan.
Det här är ett typiskt ställe då objektorientering kan vara bra. Du kan t.ex. ha din basklass för news, med all hantering och presentation. Sen kan du skriva en underklass som ärver av basklassen, men skriver över vissa villkor för hur datan ska hämtas. Vips så har du ett finurligt sätt att hålla all gemensam kod på ett ställe och ändå anpassa den.
Alternativet är väl att hämta datan i en funktion och ge den inparametrar för where, order och limit.
Det du gjort är i princip att slänga in en funktion i en klass. Det funkar men är inte riktigt objektorientering.
Det jag skulle gjort är att dela upp koden så mycket som möjligt.
En funktion som hämtar datan och skriver den i en intern variabel.
Funktioner som sätter condition, order och limit.
Och slutligen en funktion som returnerar datan.
Sen skulle jag sköta utskriften på annat sätt, t.ex. med template.
Fördelen med att separera så pass mycket är att du mha arv kan byta ut enskilda bitar väldigt enkelt. Du kan t.ex. ha en basklass för news, och en ärvd klass med speciella conditions för t.ex. en sidebar.
Av principskäl bör du aldrig sätta interna variabler med $class->variabel = data;
Man ska sträva efter att klasser ska vara self-contained och sköta sin egen datahantering. Kodar du så kan du t.ex. senare ändra hur en klass når sitt resultat utan att det påverkar övrig kod, eftersom return-värdet fortfarande är samma.
Som exempel kan vi ta om du skulle få för dig att byta databasmotor, eller optimera hur ett urval görs.
class News {
private $condition;
private $order;
private $limit;
private $page;
public function __construct() {
$this->init();
}
private function init() {
/* Här kan du sätta startvärden */
$this->condition = "";
$this->order = "news_date DESC";
$this->limit = 10;
$this->page = 1;
}
public function setCondition($condition) {
$this->condition = $condition;
}
public function setOrder($order) {
$this->order = $order;
}
public function setLimit($limit, $page) {
$this->limit = $limit;
$this->page = $page;
}
private function getConditionSql() {
/* Bygg sql tillägg här */
}
private function getLimitSql() {
/* Bygg sql tillägg här */
}
private function getOrderSql() {
/* Bygg sql tillägg här */
}
public function get_news() {
$sql = "SELECT "
."news_id, news_date, news_topic, news_text, news_picture, news_author, "
."(SELECT user_firstname FROM user WHERE user_id = site_news.news_author) AS firstname, "
."(SELECT user_lastname FROM user WHERE user_id = site_news.news_author) AS lastname "
."FROM site_news "
."WHERE 1 ";
$sql .= $this->getConditionSql();
$sql .= $this->getLimitSql();
$sql .= $this->getOrderSql();
$data = array();
/* Kod för att hämta data och stoppa in i array här */
return $data;
}
public function print_news() {
$data = $this->get_news();
$output = "";
foreach($data as $row) {
$output .= "din formatering för varje db-rad";
}
$output .= "slutkläm";
return $output;
}
}
Den riktiga vinsten med objekt kommer sen om du utnyttjar arv för att vidare anpassa ett objekt. Ta t.ex. om har en sidebar där du vill presentera nyheter, men du vill ha en mindre limit där än i huvudklassen.
class SidebarNews extends News {
private function init() {
parent::init();
$this->limit = 5;
}
}
Du kan väldigt enkelt ersätta en enstaka funktion och ärva alla andra funktioner från objektets förälder. Ett annat exempel kanske vore att ersätta print_news funktionen med en annan layout.
Angående effatas klass så skulle jag nog flytta upp limit och order funktionerna i en annan klass då de säkert används av andra liknande modeller som News. Sedan skulle jag inte ha print-funktionen i News-klassen. Det är väl inte db-modellens ska att avgöra hur datan skall visas.
Sedan om du har tillgång till PHP5 och PDO så skulle jag rekommendera användning av PDO som en databas-layer. Du skulle kunna ha en (abstrakt) basklass som alla dina db-modeller (News etc) ärver och som bidrar med en databas-connection.