Page 1 of 2
Strange problem while trying to call method.
Posted: Mon Jun 05, 2006 12:33 pm
by daedalus__
I have been trying to get a better handle on OOP with PHP.
Long story short, I'm a suck noob.
Since I can't get to the code now, I will post some pseudo code of the parts that I think are causing the problem.
Code: Select all
/* +----------------------------------------------------------+ //
// | Here is the index page | //
/* +----------------------------------------------------------+ // */
// Gloobols
global gCurrPage;
$gCurrPage = !empty($_GET['q']) ? $_GET['q'] : 'home';
// Load classes and functions
function __autoload($class_name) {
include_once("inc/$class_name.class.php"); }
include('inc/functions.inc.php');
// Carete object instances
$PageBuilder = new PageBuilder();
$DatabaseLayer = new DatabaseLayer(); // Don't judge me by my naming choices
// Build the pageeeee
$PageBuilder->BuildPage();
Code: Select all
/* +----------------------------------------------------------+ //
// | Here is the Page builder class | //
/* +----------------------------------------------------------+ // */
class PageBuilder
{
function BuildPage()
{
// calls all the other functions in order
}
function ShowTop()
{
// top html and a few pieces of non-related php
}
function ShowHeader()
{
// header html
}
function ShowCurrPage()
{
// some html
include("cnt/vnav/$gCurrPage.php"); // This is a menu bar on the left hand side; it is important and you will see why in a minute
// some more html
include("cnt/$gCurrPage.php"); // content
// yet more html
}
function ShowFooter()
{
// footer html
}
}
Now as bad as I am all of that code above there works fine. The problem I am having is here:
Code: Select all
// the vnav page
?>
<h3 class="poo">cat header</h3>
<a href="?q=askdhfsadf">a link</a>
<a href="?q=askdhfsadf">another link</a>
<a href="?q=askdhfsadf">yet another link</a>
<a href="?q=askdhfsadf">and yet another link</a>
<a href="?q=askdhfsadf">yet another and yet another link</a>
<h3 class="poo">cat header</h3>
<a href="?q=askdhfsadf">a link</a>
<a href="?q=askdhfsadf">another link</a>
<a href="?q=askdhfsadf">yet another link</a>
<a href="?q=askdhfsadf">and yet another link</a>
<a href="?q=askdhfsadf">yet another and yet another link</a>
<?php
// Here is where the scripts dies
$DatabaseLayer->MakeConnection(); // it dies, dies dies dies, dies and dies and its not nice
/* Code that displays a super neat
div containing daedalusisms
I know, i love me too */
$DatabaseLayer->BreakConnection();
?>
<h3 class="poo">cat header</h3>
<a href="?q=askdhfsadf">a link</a>
<a href="?q=askdhfsadf">another link</a>
<a href="?q=askdhfsadf">yet another link</a>
<a href="?q=askdhfsadf">and yet another link</a>
<a href="?q=askdhfsadf">yet another and yet another link</a>
<?php
The thing dies when I make that first method call. It gives a fatal error saying that the function can't be called from a non-object or something to that degree.
Now there are probably a million things you have to say but before you tell me all about my bad technique and 'there are many good DALs out there' I would apprecaite to know why that call doesn't work. I am having trouble understanding why. After that, feel free to make whatever suggestions about good technique and DALs.
I figured that since I instantiated both those objects in the index page that they would be enabled all the way down the line. Apparantly not, I don't know how to make this code work and maybe it can't, but all help is appreciated. Especially a better way of doing this. I don't know standards, and I don't know much about programming, especially OOP. I didn't even graduate high school. :- /
lol
Thanks.
Posted: Mon Jun 05, 2006 12:44 pm
by bdlang
Can you show the DatabaseLayer class definition? What does your constructor do?
Is the DatabaseLayer class php script named '
DatabaseLayer.class.php'? Check your file names, and you might want to change the
include() call to
require().
You may consider using composition to relate the DatabaseLayer class to the PageBuilder class.
Posted: Mon Jun 05, 2006 12:51 pm
by daedalus__
First, I don't know what composition is or means.
Second, I forgot to mention that class is acting up as well.
Code: Select all
class DatabaseLayer
{
function MakeConnection()
{
// these commands use constants defined in the index
// mysql link
// mysql select db
}
function BreakConnection()
{
// mysql free result
// mysql close
}
}
Now I know it's not really a data abstraction layer, but thats its name
I just want it to be there so I don't have to write the same code over and over and over - boring
i dont think i am able to use those variables outside of the function though, i am sure there is a way to use them outside of it but right now i dont know it
i only spent about 4 hours on all of this, this weekend since i am in the middle of an internet security book

Posted: Mon Jun 05, 2006 1:13 pm
by RobertGonzalez
When you can, post your actual code so we can see what is in there. Just off what you posted there are few things that need work, but seriously, post the actual code so we can see what's up.
Posted: Mon Jun 05, 2006 1:23 pm
by bdlang
Daedalus- wrote:First, I don't know what composition is or means.
Composition essentially means the 'PageBuilder' object uses the 'DatabaseLayer' object, i.e.
- Using association -> the DatabaseLayer object is used within PageBuilder object to work with page data, which is the case here.
- Using aggregation -> the DatabaseLayer object actually makes up a component of the PageBuilder class, which isn't the case.
The way you're doing it, you have a standalone, instantiated DatabaseLayer object in your script, and unless you plan on using it to pass to another object, or on it's own, you can work with it from within PageBuilder. This isn't always the best use case, it's just a suggestion.
I strongly suggest getting some OO knowledge prior to building classes with PHP. Since PHP is such an easy language to work with, it's easy enough to throw together some functions and call it a class, but that's not strictly OOP.
Daedalus- wrote:Second, I forgot to mention that class is acting up as well.
Ok, so you haven't independently tested each class, you just built them and threw them together? Create a script that thoroughly tests each class independently, then try to associate them. You still haven't shown the actual code within the DatabaseLayer class.
Daedalus- wrote:i dont think i am able to use those variables outside of the function though, i am sure there is a way to use them outside of it but right now i dont know it
Not clear on what you mean here. You generally don't want to use variables outside the object unless specific case causes you to. OOP is all about data hiding and encapsulation.
Posted: Mon Jun 05, 2006 1:54 pm
by Christopher
Maybe try something more like:
Code: Select all
$gCurrPage = !empty($_GET['q']) ? $_GET['q'] : 'home';
$PageBuilder = new PageBuilder(new DatabaseLayer(), $gCurrPage);
$PageBuilder->BuildPage();
and
Code: Select all
class PageBuilder
{
var $db;
var $curr_page;
// constructor
function PageBuilder(&$db, $curr_page) // &'s not needed in PHP5
{
$this->db =& $db;
$this->curr_page = $curr_page;
}
function ShowCurrPage()
{
$this->db->query('SELCT ....'); // get data for the page
// some html
include("cnt/vnav/{$this->curr_page}.php"); // This is a menu bar on the left hand side; it is important and you will see why in a minute
// some more html
include("cnt/{$this->curr_page}.php"); // content
// yet more html
}
}
Posted: Mon Jun 05, 2006 2:37 pm
by daedalus__
Fun.
I should have time to post the code after a half an hour or so.
What I wanted to say, though, is that I am totally suck and noob at this, and the manual doesn't do as good a job explaining classes as I would like it to have. Maybe what I am trying to do is beyond the scope of the PHP manual, but either way I am completely in the dark. I learn everything by myself using references and books, occaissionally calling upon others.
I really don't have a clue what I am doing, lol.
So, as I said, help is great. I could throw together 20 procedural scripts and have a perfectly working website, but that isn't the way to learn.
So here I am.
I'll get back to you guys in a while. Thanks for all the replies so far.
Posted: Mon Jun 05, 2006 5:17 pm
by daedalus__
Egh. Here we go.
Index.php
Code: Select all
<?php
// Start the session
session_start();
// Declare globals
global $gCurrPage;
// Set globals
$gCurrPage = !empty($_GET['q']) ? $_GET['q'] : 'home';
// Constants
define('MYSQL_HOST', 'localhost');
define('MYSQL_USER', 'root');
define('MYSQL_PASS', 'youwish');
define('MYSQL_DBNAME', 'dbname');
// Initialize classes
function __autoload($class_name) {
require_once('inc/'.$class_name.'.class.php'); }
$PageBuilder = new PageBuilder();
$DatabaseLayer = new DatabaseLayer();
// Inlude functions
require_once('inc/functions.inc.php');
// Build the page
$PageBuilder->BuildPage();
?>
pagebuilder.class.php
Code: Select all
class PageBuilder
{
private $current_page;
public function __construct()
{
$this->current_page = $gCurrPage;
}
public function BuildPage()
{
PageBuilder::ShowTop();
PageBuilder::ShowHeader();
PageBuilder::ShowMenu();
PageBuilder::ShowCurrPage();
PageBuilder::ShowFooter();
}
public function ShowTop()
{
print '
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1═strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http═equiv="Content═Type" content="text/html; charset=utf═8" />';
?>
<style type="text/css">
<!--
@import "inc/css/layout.css";
@import "inc/css/menu.css";
@import "inc/css/style.css";
-->
</style>
<!--[if IE]>
<style type="text/css" media="screen">
#menu { float:none; }
body { behavior:url("inc/csshover2.htc"); font═size:100%; }
#menu ul li { float:left; width: 100%; }
#menu h2, #menu a { height:1%;font:bold 0.7em/1.4em arial,helvetica,sans═serif; }
</style>
<![endif]-->
<title>Camicus.net ][ Home ][</title>
<?php
print '
</head>
<body>';
}
public function ShowHeader()
{
print '
<div id="oldBrowserNotice" class="hide">
<img src="img/camicus.jpg" alt="Camicus.net" />
<p>
This site will look much better in a browser that supports
<a href="http://www.webstandards.org/upgrade/"
title="Download a browser that complies with Web standards.">web
standards</a>, but it is accessible to any browser or Internet
device.
</p>
</div>
<div id="pageWrapper">
<div id="hnav" class="bottomBorderOnly">
<img src="img/banner.jpg" width="350" height="63" id="banner" alt="Camicus.net" />';
}
public function ShowMenu()
{
?>
<div id="menu">
<ul>
<li><h2>Home</h2>
<ul>
<li><a href="">personal.camicus</a></li>
<li><a href="/camicus/professional/">professional.camicus</a></li>
<li><a href="?q=admin_index">admin cp</a></li>
</ul>
</li>
</ul>
<ul>
<li><h2>Weblog</h2>
<ul>
<li><a href="">Last 5 Articles</a></li>
<li><a href="?q=weblog&a=all">All Articles</a></li>
<li><a href="?q=weblog&a=search">Search Archives</a></li>
</ul>
</li>
</ul>
<ul>
<li><h2>Projects</h2></li>
<ul>
<li><a href="?q=projects">All Projects</a></li>
<li><a href="?q=projects&a=browse">Browse Projects</a></li>
<li><a href="?q=projects&a=search">Search Projects</a></li>
</ul>
</ul>
<ul id="menuTail"><div class="tail"> </div></ul>
</div>
<?php
}
public function ShowCurrPage()
{
print '
</div>
<div id="outerColumnContainer">
<div id="innerColumnContainer">
<hr class="hide" />
<div id="rightColumn">
<div class="inside">';
/* Here is where we include the page */
if (file_exists('cnt/vnav/'.$this->current_page.'.php'))
{
include_once('cnt/vnav/'.$this->current_page.'.php');
}
else
{
include_once('cnt/vnav/home.php');
}
/* End include */
print '
</div>
</div>
<div id="contentColumn">
<hr class="hide" />
<a name="skipToContent" id="skipToContent"></a>
<div class="inside pHeader">';
/* Here is where we include the page */
if ((include_once('cnt/'.$this->current_page.'.php')) == 0)
{
echo "Apparantly there was an error, and the specified page didn't load.\n";
echo "The page probably doesn't exist, in which case you should return to the main page";
}
/* End include */
print '
</div>
</div>
<div class="clear mozclear"></div>
</div>
</div>
<div class="hide" id="nsFooterClear"><!-- for NS4\'s sake --></div>
<hr class="hide" />
<div id="footer" class="inside">';
}
public function ShowFooter()
{
?>
<p>
All HTML and CSS released into the public domain. All other intellectual property is not. Please view the <a href="?q=disclaimer" title="View the Disclaimer">Disclaimer</a>.<br />
If you experience any technical problems with this website, you can e-mail the <a href="mailto: webmaster@camicus.net" title="E═mail the Webmaster">webmaster</a>.<br />
csshover2.htc - Available for download from: http://www.xs4all.nl/~peterned/csshover.html
</p>
<?php
print '
</div>
<hr class="hide" />
</div>
</body>
</html>';
}
}
?>
databaselayer.class.php
Code: Select all
class DatabaseLayer
{
public function MakeConnection()
{
$mysql_link = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS);
mysql_select_db(MYSQL_DBNAME);
}
// I was then going to add functions to handle mysql queries
public function BreakConnection()
{
mysql_free_result($mysql_result);
mysql_close($mysql_link);
}
}
functions.inc.php - Now, I don't really need to post this but at some point it could become relevant and I would also like to have opinions on the IfLoggedIn() and AuthenticateUserCredentials functions. I am 70% that they are malfunctiong due to my inability to code. There are some garbage echo's in there for error testing, they never print to the screen :- /
I also realise that many people frown upon storing passwords in cookies and unless you have a better way that doesn't involve more database, I probably don't care. When I get the function working, more encryption will be added.
Code: Select all
<?php
function TitleOfTheDay()
{
$title = array('Home of Daedalus');
$i = rand(0, count($title)-1);
return $title[$i];
}
function FormatTimestamp($unix_timestamp)
{
return date('Hi \/\/ m\.d\.Y \/\/ \G\M\T O', $unix_timestamp);
}
function ShowErrors()
{
if (isset($_SESSION['error']))
{
print '<p class="error">'.$_SESSION['error'].'</p>';
unset($_SESSION['error']);
}
}
function IsLoggedIn()
{
if (isset($_SESSION['user']) && isset($_SESSION['password']) && isset($_SESSION['admin_flag']))
{
if (AuthenticateLoginCredentials())
{
echo "username and password are okay";
return true;
}
else
{
echo "username and password are not okay - destroying session";
session_destroy();
$_SESSION['error'] = 'You must log-in again and validate your credentials.';
return false;
}
}
}
function AuthenticateLoginCredentials()
{
$mysql_result = mysql_query(sprintf("
SELECT username, password
FROM users
WHERE username = '%s'
", $_SESSION['user']));
if (is_resource($mysql_result))
{
$row = mysql_fetch_row($mysql_result);
if ($_SESSION['password'] == md5('the_salt_string_i_use_which_you_will_never_know'.$row[1]))
{
echo "passwords did not match";
return true;
}
}
else
{
echo "user does not exist";
return false;
}
}
function QuoteOfTheDay()
{
$result = mysql_query('
SELECT quotes
FROM quotes
');
if (is_resource($mysql_result))
{
$i = 0;
while ($row = mysql_fetch_array($result, MYSQL_NUM))
{
$quote_of_the_day[$i] = $row[$i];
$i++;
}
}
else
{
$quote_of_the_day = array('No quotes!');
}
$i = rand(0, count($quote_of_the_day)-1);
print '
<div class="qotd">
'.$quote_of_the_day[$i].'
</div>
';
}
?>
cnt/vnav/home.php
Code: Select all
<div class="vnav">
<h2>
<img src="img/vnavCatPrefiix.gif" width="8" height="8" alt="" />
Home Page
</h2>
<a href="?q=construction" title="Under Construction">
under construction <span>Ω</span>
</a>
</div>
<div class="vnav">
<h2>
<img src="img/vnavCatPrefiix.gif" width="8" height="8" alt="" />
My Favorite Sites
</h2>
<a href="http://www.drudgereport.com" title="Visit http://www.drudgereport.com" target="_blank">
http://www.drudgereport.com <span>Ω</span>
</a>
<a href="http://www.sitepoint.com" title="Visit http://www.sitepoint.com" target="_blank">
http://www.sitepoint.com <span>Ω</span>
</a>
<a href="http://www.php-dev.net" title="Visit http://www.php-dev.net" target="_blank">
http://www.php-dev.net <span>Ω</span>
</a>
</div>
<?php QuoteOfTheDay(); ?>
<div class="vnav">
<h2>
<img src="img/vnavCatPrefiix.gif" width="8" height="8" alt="" />
Other Links
</h2>
<a href="?q=construction" title="Under Construction">
under construction <span>Ω</span>
</a>
</div>
I guess that I will address questions as they come. I also suppose that I am looking for suggestions more than a fix at this point. I realise that I am not going about this correctly and I wish to understand what correctly would be.
In case you are wondering why there is tons of HTML in there, someone said 'post the actual code', so I did. I tried to leave the HTML out of the earlier examples, you'll find that the page is pretty much the same as the examples I posted earlier.
Thanks for everything.
Posted: Mon Jun 05, 2006 6:47 pm
by RobertGonzalez
You may want to look at referencing your objects from your classes. I would also suggest, seeing as the pagebuilder class seems to be a simple HTML display, putting your HTML in their own files and include them rather than place them into printing methods within the class. Just a suggestion. I forgot where I heard it, but I remember seeing/hearing that a goof function/method returns a value rather than just process. Maybe look at how you can return a value from within the methods.
These all just ideas/suggestions. Take them for what you will.

Posted: Mon Jun 05, 2006 6:48 pm
by daedalus__
I had a reason for doing that the other day, but I already forget. If I remember, I will share why I did it.
Posted: Mon Jun 05, 2006 9:35 pm
by bdlang
Code: Select all
class DatabaseLayer
{
public function MakeConnection()
{
$mysql_link = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS);
mysql_select_db(MYSQL_DBNAME);
}
// I was then going to add functions to handle mysql queries
public function BreakConnection()
{
mysql_free_result($mysql_result);
mysql_close($mysql_link);
}
}
In the other code you've posted, I don't see a call to DatabaseLayer::MakeConnection(), so I guess I'll make some suggestions on this class and go from there. Your use of constants to make the connection is ok, I personally prefer to pass values into the database object, either from an included file of some sort or directly to the constructor or connect method. The problem with your class is that the variables $mysql_link and $mysql_result exist only within those methods, they are not class / object variables, i.e. that can be shared from every method in the class. So while the mysql_connect() function call may very well make a connection, that's about it. Here's an idea of what I'm talking about:
Code: Select all
class DatabaseLayer
{
// object variables
private $myLink= null; // the database connection resource link
private $myResource= null; // a resultset resource link
// a constructor, calls the MakeConnection method
function __construct() {
$this->MakeConnection();
}
public function MakeConnection()
{
$this->myLink = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS);
$this->db= mysql_select_db(MYSQL_DBNAME,$this->myLink);
}
// I was then going to add functions to handle mysql queries
public function BreakConnection()
{
mysql_free_result($this->myResource);
mysql_close($this->myLink);
}
// destructor automatically cleans up and disconnects
function __destruct() {
$this->BreakConnection();
}
}
Otherwise, the code posted previously by
arborint is what I was referring to when I was talking about association.
Posted: Tue Jun 06, 2006 11:32 am
by daedalus__
I actually, rewrote that whole class and now it contains a construct, and two functions.
It works exactly how I intended it to from the beginning by giving me a very easy and lazy way to query with one line.
I will post it it later and I hope someone will make some recommendations.
Posted: Tue Jun 06, 2006 4:30 pm
by daedalus__
This took me about 2 hours with alcohol. gallon of wine ftw!
Code: Select all
class DatabaseLayer
{
public function __construct()
{
// I know that this is bad
// I know I shouldn't be doing this
// I only did it because I wanted to write the rest of the class and this was copy+pasteable
define('MYSQL_HOST', 'localhost');
define('MYSQL_USER', 'root');
define('MYSQL_PASS', '*************');
define('MYSQL_DBNAME', '**************');
}
public function DbQuery($sql, $val = '')
{
// If $val is not empty, and it is an array
if (!(empty($val) != FALSE) && (is_array($val) != FALSE))
{
// Since the array exists we should escape the values
// to prevent SQL injection attacks on our site
foreach ($val as &$value) {
$value = mysql_real_escape_string($value); }
// Now we need to create the SQL string to be executed
$sql = vsprintf($sql, $val);
return $this->Query($sql);
}
// if ($val is not array)
// This is valid because if the first test fails
// then this part of the statement can handle
// anything else that is valid
else if ((is_array($val) == FALSE))
{
$sql = sprintf($sql, $val);
return $this->Query($sql);
}
// else return false for error;
else
{
return false;
}
}
public function Query($sql)
{
$mysql_link = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS);
mysql_select_db(MYSQL_DBNAME);
return mysql_query($sql);
mysql_close($mysql_link);
}
}
questions, comments, recommendations?
Posted: Tue Jun 06, 2006 6:27 pm
by bdlang
Daedalus- wrote:questions, comments, recommendations?
- Your design potentially assumes only one query per script (not very flexible or realistic), or multiple connections (one per query, bad bad bad).
- Your Query() method returns a value, then attempts to close the connection. Anything past the return() call will either not be called at all, or...err I don't know what happens. Maybe the server implodes.
- Your DbQuery() method, which appears to fashion a proper SQL statement, then calls Query() and returns the resultset, is interesting, I like the potential use of vsprintf() and sprintf(), but I don't see it working. Does it, in fact, work? What does the SQL statement passed to the method look like? Can you perform, for example, an INSERT, UPDATE or DELETE statement, or just SELECT?
- You're still not utilizing object variables, as in e.g. $this->connectionLink
- Query() should be at least protected, if not private, if you're going to bother assigning a visibility reference.
- ..and you're already aware the the MySQL connection parameters are hard-wired in.
That's about it for now, would be happy to help or comment on any revisions.
Posted: Tue Jun 06, 2006 6:39 pm
by daedalus__
bdlang wrote:Daedalus- wrote:questions, comments, recommendations?
- Your design potentially assumes only one query per script (not very flexible or realistic), or multiple connections (one per query, bad bad bad).
- Your Query() method returns a value, then attempts to close the connection. Anything past the return() call will either not be called at all, or...err I don't know what happens. Maybe the server implodes.
- Your DbQuery() method, which appears to fashion a proper SQL statement, then calls Query() and returns the resultset, is interesting, I like the potential use of vsprintf() and sprintf(), but I don't see it working. Does it, in fact, work? What does the SQL statement passed to the method look like? Can you perform, for example, an INSERT, UPDATE or DELETE statement, or just SELECT?
- You're still not utilizing object variables, as in e.g. $this->connectionLink
- Query() should be at least protected, if not private, if you're going to bother assigning a visibility reference.
- ..and you're already aware the the MySQL connection parameters are hard-wired in.
That's about it for now, would be happy to help or comment on any revisions.
I thought hard about whether there would be multiple queries at one time. I believe that everything I need to do can be accomplished using JOINs. I had already been thinking about how to fix the function if I did need to make more than one and I figure that I could say something like:
"SELECT * FROM users WHERE name = '$s'; SELECT * FROM images WHERE id = '%d'"
Breaking the string up on every semi-colon and then use
array('daedalus', 'some_spacer', '1')
to identify which variables are for which statement.
So far, I've only tested it with SELECT statements, but it should work with all of them because by the time the SQL string makes it to the mysql_query() function, it is a pure string with all the values escaped. One weird problem I had is that vsprintf() was appending numbers to the end of my strings.
About everything after the return, yes I know, I have only been too lazy to remove it.
bdlang wrote:
- ..and you're already aware the the MySQL connection parameters are hard-wired in.
What?
Thanks for the reply ^^ more to follow probably.
I want to actually finish this site, and do a better than mediocre job on it, so I'm looking for help.
Do you think I should rename this thread?