webForumDet fria alternativet

Fler instanser av samma objekt

12 svar · 700 visningar · startad av MickeA.com

MickeA.comMedlem sedan feb. 20034 441 inlägg
#1

Hej!

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.

Såhär har jag gjort:

$set_condition = "WHERE news_type = 1 ";
$set_order	   = "ORDER BY news_date DESC ";
$set_limit	   = "LIMIT 3";
require("module/module.news.php");

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.

Tack!

effataMedlem sedan apr. 2008137 inlägg
#2

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.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#3

Hej, tack för svaret!
Hur skulle en sådan klass kunna se ut?

Vore bra med lite exempelkod att ha som start.

Tack!

effataMedlem sedan apr. 2008137 inlägg
#4

Föreslår att du läser lite om OOP i php här http://www.php.net/manual/en/language.oop5.php
Jag är för trött för att skriva exempelkod ikväll. :)

MickeA.comMedlem sedan feb. 20034 441 inlägg
#5

Tack, ska spana in den där!

MickeA.comMedlem sedan feb. 20034 441 inlägg
#6

Nu har jag gjort följande klass:

class News {
	var $sql_condition;
	var $sql_order;
	var $sql_limit;

	function get_news(){
		$query = "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 "
				.$this->sql_condition
				.$this->sql_order
				.$this->sql_limit;
		

		$result = mysql_query($query) or die((DEBUG ? "<h2>An error occurred</h2>\n<p>" . mysql_error() . "<br /><br />\n" . $query . "</p>\n" : "<p>An error has occurred, please contact site admin.</p>\n"));
		if(!(mysql_num_rows($result) == false)){
			while($res = mysql_fetch_assoc($result)){
				if(!empty($res['news_picture'])){
					return			 "<div class=\"newsbox\">\n"
									."<h4>" . set_datetime($res['news_date'], DEFAULT_GMT, "date") . ", " . set_datetime($res['news_date'], DEFAULT_GMT, "time") . " av " . $res['firstname'] . " " . $res['lastname'] . "</h4>\n"
									."<h2>" . $res['news_topic'] . "</h2>\n"
									."<div class=\"textbox-wp\">" . $res['news_text'] . "</div>\n"
									."<div class=\"picturebox\"><img src=\"" . $res['news_picture'] . "\" alt=\"bild: " . $res['news_topic'] . "\" /></div>\n"
									."<div class=\"clearfix height-5px\">&nbsp;</div>\n"
									."<a href=\"#\" class=\"read-more\">Läs mer</a>\n"
									."</div>\n";
				}else{
					return			 "<div class=\"newsbox\">\n"
									."<h4>" . set_datetime($res['news_date'], DEFAULT_GMT, "date") . ", " . set_datetime($res['news_date'], DEFAULT_GMT, "time") . " av " . $res['firstname'] . " " . $res['lastname'] . "</h4>\n"
									."<h2>" . $res['news_topic'] . "</h2>\n"
									."<div class=\"textbox-wop\">" . $res['news_text'] . "</div>\n"
									."<div class=\"clearfix height-5px\">&nbsp;</div>\n"
									."<a href=\"#\" class=\"read-more\">Läs mer</a>\n"
									."</div>\n";
				}
			}
		}else{
			return "foo";
		}
		mysql_free_result($result);
	}
	
}

Skriver ur resultatet med:

require("inc/class.news.php");
$news = new News;
$news->sql_condition = "WHERE news_type = 1 ";
$news->sql_order	 = "ORDER BY news_date DESC ";
$news->sql_limit	 = "LIMIT 3";

$mynews = $news->get_news();

Sen kör jag echo $mynews;.

Är det här bra, finns det något jag kan ändra på i klassen ovan för att det ska fungera ännu bättre?

Tack!

effataMedlem sedan apr. 2008137 inlägg
#7

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.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#8

Aha, tack för din respons.
Ska kolla mer noggrant på det här, så får vi se om jag får ihop nått bra.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#9

Hmm, har du något mer exempel på hur jag hämtar datan med en funktion och formaterar den med en annan?

Vet inte exakt hur jag ska starta.

effataMedlem sedan apr. 2008137 inlägg
#10

Så här skulle det kunna se ut lite snabbt...

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.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#11

Aha, tack för exempelkoden!
Nu känns det som om jag lite mer att gå på.

jmeMedlem sedan maj 20012 237 inlägg
#12

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.

effataMedlem sedan apr. 2008137 inlägg
#13

Absolut jme. Ska man följa alla konstens regler bör man absolut separera mer. Detta var 2 min copy-paste för att ge MickeA lite tips. :)

129 ms totalt · 3 externa anrop · v20260731065814-full.fb544a5a
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
126 ms — hämta tråd, inlägg och bilagor (db)