View Full Version : Using OOP for Webdesign
Sardtok
04-13-2003, 04:08 AM
I've been thinking of using OOP in PHP for making maintenance easier for ChickenSoft,
but I have no idea what classes to define, and how the hierarchy should be for something like this.
Could use a little help with this.
Yeah, I will be reinventing the wheel about fifty times doing this,
but that's part of the fun isn't it?
I'll at least have a news system,
so I'll have a class for news posts.
I'll have a class for games,
maybe for users (was thinking of making it possible for members to sign up on the site).
About the news system,
should I make sorting functions in PHP,
or should I use the ORDER BY function in MySQL?
Any ideas, or references would be great.
I have designed OOP programs, just never done anything like a website,
so this is pretty abstract to me. :)
(It's a lot easier defining classes for games than a website,
at least it seems that way to me.)
Thanks guys.
pete3005
04-13-2003, 06:06 AM
As far as classes go you can run along to www.phpclasses.org and grab what you need, but I prefer to make my own based on my own needs.
Here is my datatable class, this class allows me to quickly make a 'data table' showing number of results, clickable sortable headers next/previous pages e.t.c and number of results per page.
class DataTable extends Database {
function setDataName($name){
$this->name = $name;
}
function getDataName(){
return $this->name;
}
function setRecName($recname){
$this->recname = $recname;
return $this->recname;
}
function getRecName(){
return $this->recname;
}
function setPerPage(){
if($_POST[$this->name.'pp']){
$this->pp = ($_POST[$this->name.'pp']);
} else {
$this->pp = ($_GET[$this->name.'pp']? $_GET[$this->name.'pp']:$this->getPrePP());
}
return $this->pp;
}
function preSetPP($num=5){
$this->preSetP = $num;
return $this->preSetP;
}
function getPrePP(){
return $this->preSetP?$this->preSetP:5;
}
function getPerPage(){
return $this->setPerPage();
}
function getPage(){
if($_GET[$this->getDataName().'page']>$this->getCount()){
$this->page = $this->getCount();
} else {
$this->page = ($_GET[$this->getDataName().'page']?$_GET[$this->getDataName().'page']:1);
}
return $this->page;
}
function getPageNumber(){
$this->pageno = ($this->getPage()*$this->setPerPage())-$this->setPerPage();
return $this->pageno;
}
function sortHeader($field,$label){
$str .='
<a href="'.$this->getUrlParams().$this->getDataName().'sortby='.$field.'&'.$this->getDataName().'ad='.$this->ad.'">'.$label.'</a>
';
return $str;
}
function getPageFrom(){
if($this->getCount()>($this->getPerPage()*$this->getPage())-$this->getPerPage()+1){
return ($this->getPerPage()*$this->getPage())-$this->getPerPage()+1;
} else {
return $this->getCount();
}
}
function getPageTo(){
if($this->getCount()>($this->getPage()*$this->getPerPage())){
return ($this->getPage()*$this->getPerPage());
} else {
return $this->getCount();
}
}
function moveNext(){
if($this->getCount()>$this->getPageTo()){
$str .= '
<a href="'.$this->getUrlParams().$this->getDataName().'page='.($this->getPage()+1).'">Next</a>';
}
return $str;
}
function movePrevious(){
if($this->getPage()>1){
$str = '
<a href="'.$this->getUrlParams().$this->getDataName().'page='.($this->getPage()-1).'">Previous</a> ';
}
return $str;
}
function setSortField($sortby){
$this->sortby = ($_GET[$this->name.'sortby']? $_GET[$this->name.'sortby']:$sortby);
$this->ad = ($_GET[$this->name.'ad']==$this->getPreSort()?$this->getPreSortOpp():$this->getPreSort());
}
function preSetSort($srt='DESC'){
$this->preSetS = $srt;
return $this->preSetS;
}
function getPreSort(){
return $this->preSetS?$this->preSetS:'DESC';
}
function getPreSortOpp(){
if($this->ad =='DESC'){
return 'DESC';
} else {
return 'ASC';
}
}
function setCount($countsql){
$this->sqlresult = $this->runQuery($countsql);
$this->ct = mysql_fetch_array($this->sqlresult);
$this->ctn = $this->ct[0];
return $this->ctn;
}
function getCount(){
return $this->ctn;
}
function setUrlParams(){
$this->urlparams =
$_SERVER['PHP_SELF'].'?'.$this->getExParams().$this->getDataName().'pp='.$this->getPerPage().'&'.$this->getDataName().'ad='.$_GET[$this->getDataName().'ad'].'&'.$this->getDataName().'sortby='.$this->sortby.'&';
return $this->urlparams;
}
function setExParams($ep){
$this->extraparams = $ep;
return $this->extraparams;
}
function getExParams(){
return $this->extraparams;
}
function getUrlParams(){
return $this->setUrlParams();
}
function getNumberPages(){
return ceil($this->getCount()/$this->setPerPage());
}
function setNavIndex(){
$this->navIndex = null;
for($i = 1; $i < $this->getNumberPages()+1; $i++){
if($this->getPage()==$i){
if($this->getNumberPages()!=$i){
$this->navIndex .= ' <strong>'.$i.'</strong> | ';
}
if($this->getNumberPages()==$i){
$this->navIndex .= ' <strong>'.$i.'</strong>';
}
}else {
if($i<$this->getPage()+5 && $i>$this->getPage()-5){
$this->navIndex .= ' <a href="'.$this->getUrlParams().'&'.$this->getDataName().'page'.'='.$i.'">'.$i.'</a> | ';
}
}
}
return $this->navIndex;
}
function getNavIndex(){
$str .= $this->movePrevious().$this->setNavIndex().$this->moveNext();
return $str;
}
function setPageSelector($selectors){
$str .= 'Select Number of '.$this->getRecName().' per page:<br />';
for($i=0;$i<count($selectors);$i++){
$str .='<a href="'.$this->getUrlParams().'&'.$this->getDataName().'page=1&'.$this->getDataName().'pp='.$selectors[$i].'#psort">'.($this->getPerPage()== $selectors[$i] || !$this->getPerPage()? "<strong>$selectors[$i]</strong>" : $selectors[$i]).'</a> - ';
}
$str = substr($str,0,-2);
return $str;
}
function noLimit($off){
$this->limit = $off;
return $this->limit;
}
function getQuery($sql){
$this->sql = $sql;
$this->sql .= ' ORDER BY '. $this->sortby.' '. $this->ad;
if(!$this->limit){
$this->sql .= ' LIMIT '.mysql_escape_string($this->getPageNumber()).','.mysql_escape_string($this->setPerPage());
}
$this->result = $this->runQuery($this->sql);
}
}
that class extends my database class which is:
class Database {
var $host = HOST;
var $username = USERNAME;
var $password = PASSWORD;
var $dbname = DBNAME;
function Database(){
$this->conn = @mysql_connect($this->host,$this->username,$this->password);
$this->getConnection();
$this->selectDatabase($this->dbname);
}
function getConnection(){
return $this->conn;
}
function selectDatabase(){
mysql_select_db($this->dbname);
}
function runQuery($query){
$this->sql = $query;
$this->result = mysql_query($this->sql)or die(mysql_error().'<p> </p>'.mysql_errno().'<p> </p>'.$this->sql);
return $this->result;
}
function getRow(){
$this->row = mysql_fetch_object($this->result);
return $this->row;
}
function getARow(){
$this->row = mysql_fetch_array($this->result);
return $this->row;
}
function numRows(){
return mysql_num_rows($this->result);
}
function dataSeek(){
return mysql_data_seek($this->result,0);
}
function getAffectedRows(){
return mysql_affected_rows();
}
function cleanData(){
while(list($key, $Value) = each($_GET)){
if(is_string($_GET[$key])){
$_GET[$key] = trim(addslashes($_GET[$key]));
}
}
while(list($key, $Value) = each($_POST)){
if(is_string($_POST[$key])){
$_POST[$key] = trim(addslashes($_POST[$key]));
}
}
}
function stripSlash(){
reset($_GET);
while(list($key, $Value) = each($_GET)){
if(is_string($_GET[$key])){
$_GET[$key] = trim(stripslashes($_GET[$key]));
}
}
reset($_POST);
while(list($key, $Value) = each($_POST)){
if(is_string($_POST[$key])){
$_POST[$key] = trim(stripslashes($_POST[$key]));
}
}
}
}
The 'interface ' for the datatable class would be something like this:
$news = new DataTable();
$news->setDataName('mynews');
$news->setSortField('news_date');
$news->setRecName('News Entries');
$news->setExParams('cat='.$_GET['cat'].'&');
$news->setCount("SELECT COUNT(news_id) FROM news");
$news->getQuery("
SELECT *
FROM news
");
<table width="550" class="datatable" border="0" cellspacing="1" cellpadding="3" align="center">
<?php
//check to see if we have less than 5 news items
if($news->getCount()>5){?>
<tr>
<td>
<p>Total Number <?php echo $news->getRecName();?>: <strong><?php echo $news->getCount();?></strong></p>
<?php echo $news->getRecName();?>: <?php echo $news->getPageFrom();?> to <?php echo $news->getPageTo();?> of <?php echo $news->getCount();?>
<p>
<?php echo $news->setPageSelector(array(5,10,20,30,40,50,75,100));?>
</p>
<?php
if($news->getNumberPages()>1)
echo '<strong>Pages: </strong>'. $news->getNavIndex();
?>
</p>
</td>
</tr>
</table>
<table width="550" class="datatable" border="0" cellspacing="1" cellpadding="3" align="center">
<tr>
<td>
<?php echo $news->sortHeader('news_date','Date');?>
</td>
<td>
<?php echo $news->sortHeader('news_title','News Title');?>
</td>
<td>
<?php echo $news->sortHeader('news_body','News Body');?>
</td>
<td>
Edit
</td>
<td>
Delete
</td>
</tr>
<?php
// end if less than 5 news items
}?>
<?php while($row = $news->getRow()){
$makenews .='
<tr bgcolor="#f8f8f8" class="datatable" onmouseover="bgChanger(this,\'#e6e6ff\')" onmouseout="bgChanger(this,\'#f8f8f8\')">
<td valign="top" width="100">
';
$st = strtotime($row->news_date);
$makenews .=date("D jS F Y h:i a",($st+TIME_DIFF)).'
</td>
<td valign="top" width="100">
'.$row->news_title.'
</td>
<td valign="top" width="270">
'.substr(nl2br($row->news_body),0,100).' ...
</td>
<td valign="top" width="40">
<a href="news-edit.php?cat='.$_GET['cat'].'&id='.$row->news_id.'">Edit</a>
</td>
<td valign="top" width="40">
<a href="news-delete.php?cat='.$_GET['cat'].'&id='.$row->news_id.'">Delete</a>
</td>
</tr>
';
}
echo $makenews;
?>
<tr>
<td colspan="6">
<br />
<?php
if($news->getNumberPages()>1)
echo '<strong>Pages: </strong>'.$news->getNavIndex();
?>
</td>
</tr>
</table>
I'm actually working on a live project now but can put up some examples later if you wish to see the datatable class in action.
HTH
Pete
pete3005
04-13-2003, 06:34 AM
I just visited your site, I see you are a Java programmer, ah well, you will be able to do the PHP stuff in your sleep then :)
Just played your game too :).... nice work.
Pete :)
Sardtok
04-13-2003, 06:37 AM
Thanks Pete...
I kinda had a feeling you would answer this one :)
Going to look into the php template system as well...
Not sure if I will be using it,
or if I at all need it.
(It's mostly for scripts that are supposed to be used on a lot of sites, like a bbs isn't it? Of course it doesn't hurt using it,
let's you reuse stuff more easily I guess...)
EDIT:
Hehe,
while I was typing this it seems you added another reply...
Well they need a little updating.
Will most likely do a small update to the actual games,
and then I'll update them to Java 2 instead of the old system.
BTW. Starcruiser was my second real project,
had done a website rollover menu system before that.
Before that again, I had mostly read source and tested programs in books and stuff...
pete3005
04-13-2003, 06:44 AM
A template system is useful if you work in a design team and the graphic/html guys want to edit around your code, obviously its easier to use place holders like { news results} than perhaps entangled PHP code.
Having said that as a 'one man band' I just find taking a loosely based OOP approach enough to separate my business logic from my presentation logic.
The main benefits of OOP for me is making classes that I know work and are reusable so I don't spend many hours doing the same things again and again.
Also assuming I designed my classes properly to start with any changes to the class shouldn't mean any changes to the interface so bug fixes, code modifications can be done in one central place and filter through to every site, or at least should do :)
I still fairly new to OOP myself so I am still learning all the time. I'm learning some Java now to help me use OOP properly, as you will know its more than just a concept to string a bunch of functions together :)
Pete
Edited -> Have you ever played with Flash? That is OOP (ActionScript) and like PHP I am sure you will find it a breeze. Flash is very poweful now especially PHP/MySQL/Flash combination.
Sardtok
04-13-2003, 07:07 AM
Yep,
OOP requires quite a bit of preparations if you want to do it properly.
Games for instance have a fairly simple structure though.
One class (most likely a thread of some kind) that is actually running the show.
A Player class (depends on the project though, for instance for a mud or graphical mud you would like it to extend some abstract creature or character class, as they will most likely have the same type of attributes).
An abstract enemy class if you use enemies,
and then some enemy subclasses.
Those are your basic game classes.
As well you would probably like some reusable game libraries,
like Sprite classes, Audio classes, Map classes (parsing, tileset class and so on)...
JavaPong on my site is pretty much a procedural program (it uses objects, but there is just a single Class which is JPong)...
StarCruiser is halfway object oriented,
there is an abstract Enemy class, and some subclasses for each of the different enemy types, and a single class that handles everything but AI really.
So they aren't that good OOP implementations.
OOP is really a modern implementation of Plato's philosophies for programming, I prefer OOP over procedural programming, but for some things OO just isn't needed (Like JPong which is a very very small program). ;)
vBulletin® v3.6.5, Copyright ©2000-2008, Jelsoft Enterprises Ltd.