3

Up until now all of my websites have been written in very linear code (thanks QBASIC!) which has often caused me grief with repeating, messy and unweilding code. Every dynamic page has always had its own seperate .php file, and I never used functions.

I'm rewriting the entire site now using OOP with Smarty as the template engine and could really use some guidance.

Here is my current process:

1) Visitor hits on index.php?/view/fluffybunny. index.php is just a handler for the rest of the website:

// main config holds all database, sphinx and memcached settings
// and also connects to server
require_once '../config/site.cfg.php';

$urlPath = explode('/',$_GET['path']);

$page = new page($tpl,$db);

if (!empty($urlPath[1]))
{
    switch ($urlPath[1])
    {
        case 'view': $page->view($urlPath); break;
        case 'browse': $page->browse($urlPath); break;
        case 'index': $page->index($urlPath); break;
        default: $page->index($urlPath); break;
    }
}
else
{
    header('HTTP/1.0 404 Not Found'); // then 404 because we dont want seo issues
    exit("File not found");
}

2) 'new page()' then fires off an autoloader to include page.class.php:

/* page Class
 * Created by James Napier 16/05/2013
 * Revision 0.1
 */
class page
{
    private $tpl;
    private $db;

    public function __construct($tpl='',$db='') {
        $this->tpl = $tpl;
        $this->db = $db;
    }   

    /*
    * Displays index page 
    * Depending on URL it either displays a local index or countrywide index
    */
    public function index($urlPath)
    {
        $locUrl = '';

        if (!empty($urlPath[3])) //this is the location part
        { 
            // init location class
            $location = new location($this->db);

            // check whether location exists
            if($location->checkByUrl($urlPath[3]))
            {
                $locUrl = '/in/'.$urlPath[3]; // if it does add location suffix to urls
            } 
            else
            { 
                // if it doesnt, 404 
                header('HTTP/1.0 404 Not Found');
                exit("File not found");
            }
        }

        // assign location url to template
        $this->tpl->assign('locUrl', $locUrl);

        // homepage breadcrumbs
        $this->tpl->assign('breadCrumbs',array(
            array('title'=>'Site '.COUNTRY_CODE1, 'friendlyurl'=>'/'),
            array('title'=>'Home', 'friendlyurl'=>'/')));   

        // Build the template and display it
        $this->tpl->display('index.tpl');
    }


    /*
    * Displays individual listing 
    * Uses the ID from the end of the URL to display the correct item 
    */  
    public function view($urlPath)
    {   
        $id = end($urlPath);

        if (!empty($id))
        {
            // Retrieve the article from the database along with POINT values
            $stmt = $this->db->prepare('SELECT *, X(locpoint) as x, Y(locpoint) as y FROM listing WHERE id = :id LIMIT 1');
            $stmt->bindValue(':id', $id, PDO::PARAM_INT);
            $stmt->execute();

            if($listing = $stmt->fetch(PDO::FETCH_ASSOC))
            {
                // Deal with the article status
                if ($listing['status'] == 'deleted')
                {
                    $this->err404();
                }
                elseif ($listing['status'] == 'disabled')
                {
                    $this->tpl->assign('bannerErr','THIS AD HAS EXPIRED AND IS PENDING DELETION');
                }
                elseif ($listing['status'] == 'pending')
                {
                    $this->tpl->assign('bannerErr','THIS AD IS NOT YET ACTIVE AND IS BEING REVIEWED BY THE FLOGR TEAM');            
                }

                // Start building the basic page vars from the results
                $this->tpl->assign('itemID', $listing['id']);
                $this->tpl->assign('itemTitle',$listing['title']);
                $this->tpl->assign('itemDescription',$listing['description']);
                $this->tpl->assign('itemShortDesc',$listing['shortdesc']);

                // price
                $this->tpl->assign('itemPrice', number_format($listing['price']));
                $this->tpl->assign('itemPriceTag',$listing['pricetag']);

                // location details
                $this->tpl->assign('itemLatLng', $listing['x'].','.$listing['y']);
                $this->tpl->assign('itemLocation', $listing['loctext']);

                // contact details
                $this->tpl->assign('itemContactName',$listing['name']);
                $this->tpl->assign('itemContactNo', $listing['phone']);
                $this->tpl->assign('itemContactType', $listing['type']);

                // images
                $this->tpl->assign('itemImages', json_decode($listing['images'], true));


                // Retrieve the category info for breadcrumbs and titles
                $getContent = new getContent();

                // breadcrumbs
                $this->tpl->assign('breadCrumbs',$getContent->breadCrumbs($listing['catid'],'/browse/', $this->db));


                // Page and SEO titls
                $this->tpl->assign('headTitle',$listing['title'].' located in '.$listing['loctext'].' | site.com');
                $this->tpl->assign('headDesc', $listing['shortdesc']);

                // Build the template and display it
                $this->tpl->display('view_ad.tpl');

                // Update hits and set viewed session var
                $_SESSION['filter']['viewed'][] = $listing['id'];
                $stmt = $this->db->query('UPDATE LOW_PRIORITY listing SET hits = hits+1 WHERE id = '.$listing['id']);
            }
            else
            {
                $this->err404();
            }
        }
        else
        {
            $this->err404();
        }   
    }


    /*
    * standard 404 error 
    */  
    public function err404()
    {
        header('HTTP/1.0 404 Not Found');
        exit("File not found");
    }
}

So firstly my question is, can anybody see any obvious mistakes I'm making as a newbie to OOP?

Secondly, I have some large blocks of code that need to be run on every page (user authentication..etc) regardless of whether the index.php handler has called $page->index(), $page->view()...etc. How would I integrate this code into page.class.php?

James
  • 656
  • 2
  • 10
  • 24
  • I agree with @IanBrindley on this. CodeIgniter has excelent documentation, or you could also try Laravel. It will be worth the time to study the docs and learn how to pull it off, instead of relying on spagheti code. – elvispt May 29 '13 at 20:07
  • 6
    @IanBrindley , I would like to point out, that **CodeIgniter is one of the worst frameworks in PHP**. Please stop recommending bad quality software to newbies. – tereško May 29 '13 at 20:11
  • For preference I like Zend Framework... it doesn't try forcing too much on you. – Orangepill May 29 '13 at 20:21
  • I was looking into CakePHP, but to be honest after 8 years of bashing out spaghetti PHP code all these frameworks seem to make easy things harder and hard things only a little easier? I tend to know what I want to achieve, the logic behind it and most of the native PHP functions to help me achieve it. What I lack is structure and finesse which is the main reason why I'm trying my hand at OOP. – James May 29 '13 at 20:42
  • @tereško `"feel free to ignore"`. If you want something extremely basic that will just give that OOP structure and not a disconnected framework, rip apart opencarts MVC system. – Ian Brindley May 29 '13 at 21:06
  • @IanBrindley , static variables, global state and outdated object-related code is not something a newbie should be "learning". CakePHP does not adhere to object-oriented paradigm or principles that define it. And no, I prefer not to ignore stuff that is actively harmful to newbies. – tereško May 29 '13 at 21:32
  • Aside from framework suggestions, can anybody give me some critique on my code and any common OOP blunders I may be making? Also is there any issue with calling other classes (authentication..etc) from within the __contstruct() function of my page display class? – James May 30 '13 at 07:51

1 Answers1

0

As far as your code goes you're doing just fine in doing OOP but by programming a framework from scratch you're basically reinventing the wheel. I highly recommend using an existing framework like: CakePHP, Zend Framework, or Laravel. After you've used frameworks for a while you start to get a handle of what you like and what you don't like. At that point making your own framework is a good exercise. But even at that point you should realize that the open source frameworks out there have been developed using 100's, if not 1,000's of man/woman hours and while each framework will probably have quirks you don't like, dealing with those quirks is a lot easier than building a framework from scratch.

chrislondon
  • 12,487
  • 5
  • 26
  • 65
  • Thanks for the comment chris. I think you're right and I should start from scratch with a framework. My problem is that I tend to get too caught up on performance and worry about how the app will scale in the future rather than how it will work now. What I need is a developer who can get me started with a framework and show me the ropes in a way that is relevant to my project. The examples on the net are too far detached from my app needs and it seems like a slow learning curve to get to where I am with spaghetti code. – James Jun 10 '13 at 21:06
  • Sounds like a plan. Unfortunately you won't be able to find that type of help on SO. – chrislondon Jun 10 '13 at 21:26