PHP Autoload not working?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
Cirdan
Forum Contributor
Posts: 144
Joined: Sat Nov 01, 2008 3:20 pm

PHP Autoload not working?

Post by Cirdan »

I have the following Autoload function to load classes based on their name.

Code: Select all

 public static function loadClass($classname) {
        
      $path = ROOT_PATH . '/' . str_replace('_', '/', $classname) . '.php';
      
      if(file_exists($path)) {
          include $path;
          
          
          if(class_exists($classname)) {
              return true;
          } else {
             //throw new Exception('Class '.$classname.' was not found by the autoloader');
             return false;
          }
      }
      
      //throw new Exception('File '.$path.' was not found by the autoloader.');
      return false;
  }
Then in my Router to load the class, I have this code:

Code: Select all

 
  public function handleRequest()
  {
      $originalURI = $this->getRequestURI();
      $uri = explode('/', $originalURI);
      
      // The first element in the array is always empty
      array_shift($uri);
      
      if(empty($uri[0])) {
          // The default route
          $classname = 'Page_'.$this->_defaultPage.'_Action_'.$this->_defaultAction;
          
      } elseif(empty($uri[1])) {
          // Capitalize the first letter
          $uri[0] = ucwords($uri[0]);
          
          // We want to support .rss and other file types
          // the action will just be called something like
          // 
          // /forum.rss = Page_Forum_Action_IndexRSS
          $action = explode('.', $uri[0]);
          
          if(isset($action[1])) {
              $action = $this->_defaultAction.strtoupper($action[1]);
          } else {
              $action = $this->_defaultAction;
          }
          
          $this->_page = $uri[0];
          $this->_action = $action;
          
          $classname = 'Page_'.$uri[0].'_Action_'.$action;
          
          // Pop it off the array
          array_shift($uri);
          
      } else {
          // Capitalize the first letter
          $uri[0] = ucwords($uri[0]);
          $uri[1] = ucwords($uri[1]);
          
          // We want to support .rss and other file types
          // the action will just be called something like
          // 
          // /forum/index.rss = Page_Forum_Action_IndexRSS
          $action = explode('.', $uri[1]);
          
          if(isset($action[1])) {
              $action = $action[0].strtoupper($action[1]);
          } else {
              $action = $uri[1];
          }
          
          $this->_page = $uri[0];
          $this->_action = $action;
          
          $classname = 'Page_'.$uri[0].'_Action_'.$action;
          
          // Pop it off the array
          array_shift($uri);
          array_shift($uri);
      }
      
      
      // parse the parameters to make sure they are safe
      foreach($uri as &$param) {
          $param = str_replace(' ', '-', $param);
          $param = strip_tags($param);
      }
      
      if(class_exists($classname)) {
          if(!empty($uri)) {
              // We pass the remaining parts of the URI
              // for use by the page
              $class = new $classname($uri);
          } else {
              $class = new $classname();
          }
          
          return $class;
      } else {
          // 404!
          return false;
      }
  }
Now, on my local MAMP server running PHP 5.2.3 this works perfectly as expected. On a remote development server running PHP 5.2.9, it gives me an error saying that it can't find the class. Why is it working as expected on my local computer, but not the remote server? Am I missing some sort of case sensitivity some where or something? If I enable the exceptions in the Autoloader, none of them get triggered. The ROOT_PATH is set like this in the index.php which handles all the requests.

Code: Select all

define('ROOT_PATH', dirname(__FILE__))
I get these errors on the remote server (if I remove the class_exists($classname) statement):

Code: Select all

[Wed Aug 19 18:37:07 2009] [error] [client 68.5.57.63] PHP Fatal error:  Class 'Page_Index_Action_Index' not found in /var/www/html/System/Router.php on line 88
[Wed Aug 19 18:37:08 2009] [error] [client 68.5.57.63] PHP Fatal error:  Class 'Page_Favicon.ico_Action_IndexICO' not found in /var/www/html/System/Router.php on line 90, referer:
 
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Re: PHP Autoload not working?

Post by Ollie Saunders »

I'm guessing from the name loadClass and the throwing of exceptions that you really want loadClass to work or fail fast otherwise, which makes sense given that when a class doesn't exist it's a fatal error for PHP. With all that being the case the implementation of loadClass could be improved by using require, which would tell you if the problem is not having access to the files.

Code: Select all

public static function loadClass($name) {
    require ROOT_PATH . '/' . str_replace('_', '/', $classname) . '.php';
}
Could be that you upload the class files correctly or ROOT_PATH correct on the production machine. Otherwise, how's your test coverage?
Cirdan
Forum Contributor
Posts: 144
Joined: Sat Nov 01, 2008 3:20 pm

Re: PHP Autoload not working?

Post by Cirdan »

I don't do any testing besides just echoing variables that might be causing problems. I put an echo in the loadClass method to see what the path comes out to be, it's correct. I also changed from include to require but no other errors. What is throwing me off is why it works on my local system but not the server. I assume it has to be with some quirk with Linux or something strange about how PHP is configured, I just have no idea what it could be. Here is the output from my echo in loadClass

/var/www/html/System/FrontController.php
/var/www/html/System/Router.php
/var/www/html/System/View.php
/var/www/html/Page/Index/Action/Index.php

It loads the FrontController, Router, and View correctly, but there seems to be a problem with it loading the class from Page/Index/Action/Index.php. Here is what that Index.php looks like:

Code: Select all

 
<?php
 
class Page_Index_Action_Index extends System_Abstract_Action {
 
    // This method is called first.
    // This is where any and all initialization
    // required for the page should happen
    public function init() {
        $this->view->pagetitle = 'Index';
    }
 
    // This is where the buisness logic goes
    public function action() {
    }
};
Cirdan
Forum Contributor
Posts: 144
Joined: Sat Nov 01, 2008 3:20 pm

Re: PHP Autoload not working?

Post by Cirdan »

:banghead: Okay I figured it out. I had to chmod 775 all the files and directories.
Post Reply