I have a very old application script that actually loads controller, model and entity with the class name using below snippet
function __autoload($className)
{
list($filename , $suffix) = explode('_' , $className);
switch (strtolower($suffix))
{
case 'model':
$folder = '/model/';
$suffix = BIZ_SUFFIX;
break;
case 'dao':
$folder = '/entity/';
$suffix = DAO_SUFFIX;
break;
}
$file = SITE_PATH . $folder . strtolower($filename) . $suffix .'.php';
if (file_exists($file))
{
include_once($file);
}
else
{
die("File '$filename' containing class '$className' not found in '$folder'.");
}
}
Now I have problem in integrating any third party autoloaders, even with the composer autoload.
I have even tried below methods as well
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.class.php';
});
and
function my_autoloader($class) {
include 'classes/' . $class . '.class.php';
}
spl_autoload_register('my_autoloader');
Error msg:
Fatal error: Class 'Template_Model' not found
If you use spl_autoload_register, the __autoload function will not be called.
Rename __autoload to something else, ex. old_autoload. And register it in autoloaders spl_autoload_register('old_autoload');
Related
I have created the MVC directory structure and started with writing an "App" class.
Everything works well on the local machine using WAMP. But it fails when uploaded to the hosting server.
So, I compared PHP settings between host and local, all looks good, everything matches version etc. I checked paths etc.
Here is my PRIVATE directory structure:
This is the PUBLIC area
This is the index.php file:
<?php
require_once '../httpd.private/init.php';
require_once '../httpd.private/core/App.php';
$app = new App;
?>
Which loads the INIT.PHP variables:
<?php
// Define path constants
define("DS", DIRECTORY_SEPARATOR);
define("ROOT", getcwd() . DS);
define("APP_PATH", ROOT . '../httpd.private' . DS);
define("VIEW_PATH", ROOT . "views" . DS);
define("MODEL_PATH", APP_PATH . "models" . DS);
define("DATA", APP_PATH . "data" . DS);
define("CORE_PATH", APP_PATH . "core" . DS);
define("CONTROLLER_PATH", APP_PATH . "controllers" . DS);
define('SEC_PATH', APP_PATH . "sec" . DS);
define("UPLOAD_PATH", APP_PATH . "uploads" . DS);
define('FILE_ENCRYPTION_BLOCKS', 10000);
$modules = [ROOT, APP_PATH, VIEW_PATH, MODEL_PATH, DATA, CORE_PATH, CONTROLLER_PATH, SEC_PATH];
set_include_path(get_include_path(). PATH_SEPARATOR . implode(PATH_SEPARATOR,$modules));
spl_autoload_register('spl_autoload', false);
?>
After the init file the App.php kicks in:
<?php
class App
{
protected $controller = 'homeController';
protected $method = 'index';
protected $params = [];
public function __construct()
{
$this->parseUrl();
if (file_exists(CONTROLLER_PATH . $this->controller . '.php'))
{
$this->controller = new $this->controller;
if (method_exists($this->controller, $this->method))
{
call_user_func_array([$this->controller, $this->method], $this->params);
} else {
header("Location: /home/index");
}
} else {
header("Location: /home/index");
}
exit();
}
public function parseUrl()
{
if (isset($_GET['url'])){
$url = explode('/', filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL));
$this->controller = isset($url[0]) ? $url[0] . 'Controller' : 'homeController';
$this->method = isset($url[1]) ? $url[1] :'index';
unset($url[0], $url[1]);
$this->params = !empty($url) ? array_values($url) : [];
}
}
}
?>
The ERROR:
Fatal error: Uncaught Error: Class 'homeController' not found in
/customers/2/e/9/something.com/httpd.private/core/App.php:15
Stack trace: #0 /customers/2/e/9/something.com/httpd.www/index.php(5): App->__construct() #1 {main} thrown in /customers/2/e/9/something.com/httpd.private/core/App.php on line 15
This is line 15 that is mentioned in the error:
$this->controller = new $this->controller;
And here is the controller.php file:
<?php
class Controller
{
protected $view;
protected $model;
public function __construct()
{
/* echo "This is the Class: " . __CLASS__ . "<br>";
echo "And this is the Method: " . __METHOD__ . "<br>";
die(); */
}
public function view($viewName, $data = [])
{
$this->view = new View($viewName, $data);
return $this->view;
}
public function model($modelName, $data = [])
{
if (file_exists(MODEL_PATH . $modelName . 'Model' . '.php')){
require MODEL_PATH . $modelName . 'Model' . '.php';
$this->model = new $modelName;
}
}
}
?>
How can I correct the error and perhaps better improve the code?
I am aware that I could start with using composer and other frameworks, but that will not help my homework.
I don't see any line where you include your controller file.
Before the instantiation of your controller, you need to require the script.
(You have done that with your model)
I have a question i have an error im not enabled to fix. The error is saying the name is already in use.
What im trying to do is im calling a API that needs to give some response back. Because of this error im not enabled to acces the data of my API
The Error
Cannot declare class ComposerAutoloaderInitd1e500cc63b56a87596c43fefa8d9495, because the name is already in use in
This is my autoload.php
<?php
// autoload.php #generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitd1e500cc63b56a87596c43fefa8d9495::getLoader();
autoload_real.php
<?php
// autoload_real.php #generated by Composer
class ComposerAutoloaderInitd1e500cc63b56a87596c43fefa8d9495
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitd1e500cc63b56a87596c43fefa8d9495', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitd1e500cc63b56a87596c43fefa8d9495', 'loadClassLoader'));
$includePaths = require __DIR__ . '/include_paths.php';
$includePaths[] = get_include_path();
set_include_path(implode(PATH_SEPARATOR, $includePaths));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitd1e500cc63b56a87596c43fefa8d9495::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}
I had this issue when including two composer autoloaders from two directories where one originated as a copy of the other one (don't ask me why).
Based on this GitHub Issue I concluded my solution:
Delete the composer lock-file (e.g. composer.lock) and execute composer update.
In my case I just deleted the vendor-directory too.
I'm trying to make this work:
function autoload($dir, $className) {
$filename = $dir . $className . ".php";
if (file_exists($filename)) {
include($filename);
if (class_exists($className)) {
return true;
}
}
return false;
}
function loader ($dir, $class) {
spl_autoload_register(array($dir, 'autoload' ));
}
But when using loader('pathtofile', 'classname');
I'm getting an error
Passed array does not specify an existing static method
My question is how can I pass $dir variable to loader function?
Looks like you are trying to set up your autoloader incorrectly, so I'll stop you there :O. You would want to set a constant which you can use in your function. You should have your autoloader in an included file that will be used in each page loading classes
<?php
//inc.php
//Set constant
define('SOME_DIR','/some/dir');
spl_autoload_register(function($name){
if(file_exists(SOME_DIR.$name.'.php')){
require SOME_DIR.$name.'.php';
}else{
echo 'The class '.$name.' could not be found';
}
});
?>
In the file that will be using classes
<?php
//top of file
require 'someDir/inc.php';
//Do something
?>
I hope this is what you need:
function loader ($dir) {
spl_autoload_register(function($class) use ($dir) {
$filename = $dir . $class . ".php";
if (file_exists($filename)) {
include($filename);
if (class_exists($class)) {
return true;
}
}
return false;
});
}
loader('pathtofile');
In my application/core directory, I had class MY_Controller.
And now, I want to create two classes in two paths application/core/Frontent/Frontend_Controller.php and application/core/Backend/Backend_Controller.php. Then my modules controllers extend from Frontend_Controller and Backend_Controller class.
But CI always raises class not found error.
Edit March 20th 2014:
I used #manix's suggestion:
1. Write below script at the end of /application/config/config.php
function __autoload($class)
{
if (strpos($class, 'CI_') !== 0)
{
if (file_exists($file = APPPATH . 'core/Frontend/' . $class . EXT))
{
include $file;
}
if (file_exists($file = APPPATH . 'core/Backend/' . $class . EXT))
{
include $file;
}
}
}
Create /application/core/Backend/Backend_Controller.php like this:
(defined('BASEPATH')) OR exit('No direct script access allowed');
class Backend_Controller extends CORE_Controller {
}
I have a Menu class extends Backend_Controller. Then receive this error Fatal error: Class 'Backend_Controller' not found in codeigniter\application\widgets\menu\Controllers\menu.php on line 6. If I put the Backend_Controller.php at /application/core/Backend_Controller.php, it is OK. But I want to put it into a subfolder.
SOLUTION (update March 24th 2014)
Thank to manix. I edited from his code to load classes. Here is the code that works for me.
function __autoload($class) {
if (strpos($class, 'CI_') !== 0) {
if (file_exists($file = APPPATH . 'core/Frontent/' . $class . EXT)) {
include $file;
}
if (file_exists($file = APPPATH . 'core/Backend/' . $class . EXT)) {
include $file;
}
if (file_exists($file = APPPATH . 'core/' . $class . EXT)) {
include $file;
}
}
}
Try to call explicitly the __autoload funtionat the end of the config.php file that raised at application/config/ folder. Look the example above:
function __autoload($class)
{
if (strpos($class, 'CI_') !== 0)
{
if (file_exists($file = APPPATH . 'core/Frontent/' . $class . EXT))
{
include $file;
}
if (file_exists($file = APPPATH . 'core/Backend/' . $class . EXT))
{
include $file;
}
}
}
All,
I am reading the following article on a lightweight PHP dynamic front controller: http://www.w3style.co.uk/a-lightweight-and-flexible-front-controller-for-php-5
Here is the code:
index.php
<?php
define("PAGE_DIR", dirname(__FILE__) . "/pages");
require_once "FrontController.php";
FrontController::createInstance()->dispatch();
FrontController.php
<?php
class FrontController {
public static function createInstance() {
if (!defined("PAGE_DIR")) {
exit("Critical error: Cannot proceed without PAGE_DIR.");
}
$instance = new self();
return $instance;
}
public function dispatch() {
$page = !empty($_GET["page"]) ? $_GET["page"] : "home";
$action = !empty($_GET["action"]) ? $_GET["action"] : "index";
//e.g. HomeActions
$class = ucfirst($page) . "Actions";
//e.g. pages/home/HomeActions.php
$file = PAGE_DIR . "/" . $page . "/" . $class . ".php";
if (!is_file($file)) {
exit("Page not found");
}
require_once $file;
$actionMethod = "do" . ucfirst($action);
$controller = new $class(); // I DON'T UNDERSTAND WHAT THIS DOES...
if (!method_exists($controller, $actionMethod)) {
exit("Page not found");
}
//e.g. $controller->doIndex();
$controller->$actionMethod();
exit(0);
}
}
pages/guestbook/GuestbookActions.php
<?php
class GuestbookActions {
public function doIndex() {
echo "Index action called...";
}
public function doCreatePost() {
echo "CreatePost action called...";
}
}
In the front controller class, could someone explain to me what $controller = new $class(); does? I don't understand it. It seems to be creating a class on the fly? In the example above, $class is a string with a value like "HomeActions". So $controller would be a new instance of a class named "HomeActions", but those are not defined anywhere. I'm confused.
Many thanks,
JDelage
$controller = new $class();
That does indeed create a new object of the type contained in $class, so it is equivalent to $controller = new HomeActions() in your example. From the manual:
If a string containing the name of a class is used with new, a new instance of that class will be created
The classes are not all present initially. However, the necessary one is loaded dynamically:
$file = PAGE_DIR . "/" . $page . "/" . $class . ".php";
if (!is_file($file)) {
exit("Page not found");
}
require_once $file;
require_once loads the file which presumably contains the class definition, so you can create the object as shown above.
The example request in the article is to http://localhost/index.php?page=guestbook&action=index, so $class would be GuestbookActions, which is defined in the third code sample.