spl_autoload with namespace php - php

I am makeing a small framework for scheduled job that are run by a nodejs external process. I would like to use an auto loader but for some reason data is not getting to it. I am also using namespaces. Here is what my folder structure looks like:
Library
|_ Core
|_ JobConfig.php
|_ Utilities
|_ Loader.php
|_ Scheduled
|_ SomeJob.php
|_ Config.php
My Config.php just has some definitions and an instance of my Loader.php.
Loader.php looks like:
public function __constructor()
{
spl_autoload_register(array($this, 'coreLoader'));
spl_autoload_register(array($this, 'utilitiesLoader'));
}
private function coreLoader($class)
{
echo $class;
return true;
}
private function utilitiesLoader($lass)
{
echo $class;
return true;
}
So for my SomeJob.php I am including Config.php and then try to instantiate JobConfig.php when it fails. My namespaces look like Library\Core\JobConfig and so on. I am not sure if this is the best approach without the ability to bootsrapt things. But I am not seeing the echo's from the loader before it fails.
Edit:
I tried the sugestion by #Layne but did not work. I am still getting a class not found and seems like the class in not getting in the spl stack. Here is a link to the code

If you actually use namespaces in the same way you're using your directory structure, this should be rather easy.
<?php
namespace Library {
spl_autoload_register('\Library\Autoloader::default_autoloader');
class Autoloader {
public static function default_autoloader($class) {
$class = ltrim($class, '\\');
$file = __DIR__ . '/../';
if ($lastNsPos = strrpos($class, '\\')) {
$namespace = substr($class, 0, $lastNsPos);
$class = substr($class, $lastNsPos + 1);
$file .= str_replace('\\', '/', $namespace) . '/';
}
$file .= $class . '.php';
include $file;
}
}
}
Put that into your Library directory and require it on a higher level. Hopefully I didn't mess that one up, didn't test it.
EDIT: Fixed path.

use this class to index of your project, just replace WP_CONTENT_DIR with another directory level to scan php files, this class automatically include files:
<?php
class autoloader
{
public static function instance()
{
static $instance = false;
if( $instance === false )
{
// Late static binding
$instance = new static();
}
return $instance;
}
/**
* #param $dir_level directory level is for file searching
* #param $php_files_json_name name of the file who all the PHP files will be stored inside it
*/
private function export_php_files($dir_level, $php_files_json_name)
{
$filePaths = array(mktime());
/**Get all files and directories using iterator.*/
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir_level));
foreach ($iterator as $path) {
if (is_string(strval($path)) and pathinfo($path, PATHINFO_EXTENSION) == 'php') {
$filePaths[] = strval($path);
}
}
/**Encode and save php files dir in a local json file */
$fileOpen = fopen($dir_level . DIRECTORY_SEPARATOR . $php_files_json_name, 'w');
fwrite($fileOpen, json_encode($filePaths));
fclose($fileOpen);
}
/**
* #param $php_files_json_address json file contains all the PHP files inside it
* #param $class_file_name name of the class that was taken from #spl_autoload_register_register plus .php extension
* #return bool Succeeding end of work
*/
private function include_matching_files($php_files_json_address, $class_file_name)
{
static $files;
$inc_is_done = false;
if ($files == null) {
$files = json_decode(file_get_contents($php_files_json_address), false);
}
/**Include matching files here.*/
foreach ($files as $path) {
if (stripos($path, $class_file_name) !== false) {
require_once $path;
$inc_is_done = true;
}
}
return $inc_is_done;
}
/**
* #param $dir_level directory level is for file searching
* #param $class_name name of the class that was taken from #spl_autoload_register
* #param bool $try_for_new_files Try again to include new files, that this feature is #true in development mode
* it will renew including file each time after every 30 seconds #see $refresh_time.
* #return bool Succeeding end of work
*/
public function request_system_files($dir_level, $class_name, $try_for_new_files = false)
{
$php_files_json = 'phpfiles.json';
$php_files_json_address = $dir_level . DIRECTORY_SEPARATOR . $php_files_json;
$class_file_name = $class_name . '.php';
$files_refresh_time = 30;
/**Include required php files.*/
if (is_file($php_files_json_address)) {
$last_update = json_decode(file_get_contents($php_files_json_address), false)[0];
if ((mktime() - intval($last_update)) < $files_refresh_time || !$try_for_new_files) {
return $this->include_matching_files($php_files_json_address, $class_file_name);
}
}
$this->export_php_files($dir_level, $php_files_json);
return $this->include_matching_files($php_files_json_address, $class_file_name);
}
/**
* Make constructor private, so nobody can call "new Class".
*/
private function __construct()
{
}
/**
* Make clone magic method private, so nobody can clone instance.
*/
private function __clone()
{
}
/**
* Make sleep magic method private, so nobody can serialize instance.
*/
private function __sleep()
{
}
/**
* Make wakeup magic method private, so nobody can unserialize instance.
*/
private function __wakeup()
{
}
}
/**
* Register autoloader.
*/
try {
spl_autoload_register(function ($className) {
$autoloader = autoloader::instance();
return $autoloader->request_system_files(WP_CONTENT_DIR, $className, true);
});
} catch (Exception $e) {
var_dump($e);
die;
}

Related

Cannot declare class ABC, because the name is already in use

Here am getting an error like Fatal error: Cannot declare class ABC, because the name is already in use in while listing all controller names and functions in project.In order to get i got an library from surroundings and placed it.library looks like this
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
/***
* File: (Codeigniterapp)/libraries/Controllerlist.php
*
* A simple library to list al your controllers with their methods.
* This library will return an array with controllers and methods
*
* The library will scan the "controller" directory and (in case of) one (1) subdirectory level deep
* for controllers
*
* Usage in one of your controllers:
*
* $this->load->library('controllerlist');
* print_r($this->controllerlist->getControllers());
*
* #author Peter Prins
*/
class ControllerList {
/**
* Codeigniter reference
*/
private $CI;
/**
* Array that will hold the controller names and methods
*/
private $aControllers;
// Construct
function __construct() {
// Get Codeigniter instance
$this->CI = get_instance();
// Get all controllers
$this->setControllers();
}
/**
* Return all controllers and their methods
* #return array
*/
public function getControllers() {
return $this->aControllers;
}
/**
* Set the array holding the controller name and methods
*/
public function setControllerMethods($p_sControllerName, $p_aControllerMethods) {
$this->aControllers[$p_sControllerName] = $p_aControllerMethods;
}
/**
* Search and set controller and methods.
*/
private function setControllers() {
// Loop through the controller directory
foreach(glob(APPPATH . 'controllers/*') as $controller) {
// if the value in the loop is a directory loop through that directory
if(is_dir($controller)) {
// Get name of directory
$dirname = basename($controller, 'EXT');
// Loop through the subdirectory
foreach(glob(APPPATH . 'controllers/'.$dirname.'/*') as $subdircontroller) {
// Get the name of the subdir
$subdircontrollername = basename($subdircontroller, EXT);
// Load the controller file in memory if it's not load already
if(!class_exists($subdircontrollername)) {
$this->CI->load->file($subdircontroller);
}
// Add the controllername to the array with its methods
$aMethods = get_class_methods($subdircontrollername);
$aUserMethods = array();
foreach($aMethods as $method) {
if($method != '__construct' && $method != 'get_instance' && $method != $subdircontrollername) {
$aUserMethods[] = $method;
}
}
$this->setControllerMethods($subdircontrollername, $aUserMethods);
}
}
else if(pathinfo($controller, PATHINFO_EXTENSION) == "php"){
// value is no directory get controller name
$controllername = basename($controller, 'EXT');
// Load the class in memory (if it's not loaded already)
if(!class_exists($controllername)) {
var_dump($controller);
$this->CI->load->file($controller);
}
// Add controller and methods to the array
$aMethods = get_class_methods($controllername);
//var_dump($aMethods);
$aUserMethods = array();
if(is_array($aMethods)){
foreach($aMethods as $method) {
if($method != '__construct' && $method != 'get_instance' && $method != $controllername) {
$aUserMethods[] = $method;
}
}
}
$this->setControllerMethods($controllername, $aUserMethods);
}
}
}
}
// EOF
Here am getting error in the line $this->CI->load->file($controller);.when i call this library in my controller am getting error what i mentioned in title.Is it a problem of php version,Here it is telling that controller class name is already called so it cannot be call again.

Kohana: Cannot redeclare class

Unable to start project in Kohana. I have cloned it from github, than set my database info in config file and get error: Cannot redeclare class.
I have 2 methods autoload functions.
public static function auto_load($class, $directory = 'classes')
{
// Transform the class name according to PSR-0
$class = ltrim($class, '\\');
$file = '';
$namespace = '';
if ($last_namespace_position = strripos($class, '\\'))
{
$namespace = substr($class, 0, $last_namespace_position);
$class = substr($class, $last_namespace_position + 1);
$file = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;
}
$file .= str_replace('_', DIRECTORY_SEPARATOR, $class);
if ($path = Kohana::find_file($directory, $file))
{
// Load the class file
require_once $path;
// Class has been found
return TRUE;
}
// Class is not in the filesystem
return FALSE;
}
/**
* Provides auto-loading support of classes that follow Kohana's old class
* naming conventions.
*
* This is included for compatibility purposes with older modules.
*
* #param string $class Class name
* #param string $directory Directory to load from
* #return boolean
*/
public static function auto_load_lowercase($class, $directory = 'classes')
{
// Transform the class name into a path
$file = str_replace('_', DIRECTORY_SEPARATOR, strtolower($class));
if ($path = Kohana::find_file($directory, $file))
{
// Load the class file
require_once $path;
// Class has been found
return TRUE;
}
// Class is not in the filesystem
return FALSE;
}
I have tried to add class_exists() before require() but it doesn't work& What I should do to start a project?
Possibly required class is included in some other file already.
I don't know how exactly you check class collision problem, but you should do something like:
function include_quietly($file) {
$conflicts = false;
$txt = file_get_contents($file);
preg_match_all("#class\s+(\w+)\s*{#muis", $txt, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
if (class_exists($m[1])) {
$conflicts = true;
break;
}
}
if (!$conflicts)
include_once $file;
else
echo "include conflicts in file {$file}\n";
}
include_quietly($path);

Problems with autoload wordpress plugin development

My autoload is not working in wordpress (It's Not including the files), What can the problem be ?
If you read my comments you will understand it i think.
I am already trying the hole day to fix this problem. So if somebody knows the solution i really want to hear it : )
<?php
/*
Plugin Name: Test Autoload
Plugin URI: http://autoload.com
Description: Test Autoload
Version: 1.0
*/
if(!class_exists('Test_Autoload')) {
final class Test_Autoload {
public function __construct() {
Test_Autoload::register();
}
/**
* Registers Test_Autoload Loader as an SPL autoloader.
*
* #param boolean $prepend
*/
public static function register($prepend = false)
{
if (version_compare(phpversion(), '5.3.0', '>=')) {
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
} else {
spl_autoload_register(array(new self, 'autoload'));
}
}
/**
* Handles autoloading of Test_Autoload classes.
*
* #param string $class
*/
public static function autoload($class)
{
$class = plugin_dir_path(__FILE__) . 'admin/classes/' . $class .'.php';
// If the specified $class does not include our namespace return
if ( false === strpos( $class, 'Test_Autoload' ) ) {
return;
}
if (is_file($class)) {
require_once($class);
} else {
wp_die("The file attempting to be loaded at $class does not exist.");
}
}
}
}
A simple and functionnal class to autoload with or withour namespaces
enter link description here

Creating customer specific routes in Zend Framework 2

I'm developing a WebApp which (as usual) must support customer specific functionalities.
To achieve it I plan to set the customer name in the local app configuration (config/autoload/local.php )
configuration file so that I can use it to call the specialized code later on.
The module folder structure is this:
/module/Application
/module/Application/config
/module/Application/src
/module/Application/src/Application
/module/Application/src/Application/Controller
/module/Application/src/Application/Controller/[customer_instance_name]
/module/Application/src/Application/Model
/module/Application/src/Application/Model/[customer_instance_name]
/module/Application/view
/module/Application/view/Application
/module/Application/view/Application/[action]
/module/Application/view/Application/[action]/[customer_instance_name]
Using a custom ViewModel I inject the specific customer name to the template path:
namespace Application\Model;
use Zend\View\Model\ViewModel;
use Zend\View\Resolver\TemplatePathStack;
use Zend\Mvc\Service\ViewTemplatePathStackFactory;
class MyViewModel extends ViewModel
{
private $customInstanceName;
private $pathStack;
/**
* Constructor
*
* #param null|array|Traversable $variables
* #param array|Traversable $options
*/
public function __construct($variables = null, $options = null)
{
parent::__construct ( $variables, $options );
$serviceLocator = MySingleton::instance()->serviceLocator;
$factory = new ViewTemplatePathStackFactory();
$this->pathStack = $factory->createService($serviceLocator);
$config = $serviceLocator->get('config');
if (isset($config['custom_instance_name']) AND ($config['custom_instance_name']!='')) {
$this->customInstanceName = $config['custom_instance_name'];
} else {
$this->customInstanceName = false;
}
}
/**
* Set the template to be used by this model
*
* #param string $template
* #return ViewModel
*/
public function setTemplate($template)
{
$this->template = (string) $template;
if ( $this->customInstanceName === false) {
return $this;
}
$pathComponents = explode('/', (string) $template);
$last = array_pop($pathComponents);
array_push($pathComponents, $this->customInstanceName);
array_push($pathComponents, $last);
$customTemplate = implode('/', $pathComponents);
if ($this->pathStack->resolve($customTemplate) !== false) {
$this->template = $customTemplate;
}
return $this;
}
}
Using the "Decorator Pattern" I can achieve the same customization level on my Models.
I'm having problem to handle specific behavior. In this case I plan to create custom Controllers extending
my base controller class, but I'unable to call those controllers since the routing is defined on the module
config (and I was unable to change it in runtime).
My questions are:
1) Is this approach correct, or there is a better way to do it?
2) If the approach is correct, how can I define a custom router to be used when the ServiceManager reads my routing config?
Just found a solution. Will register it here hoping someone will benefit from it.
All I had to do was to create a specific router class with a match method which returns the correct routing target for each customer controller, and add it to my module.config.php as the type for each action.
namespace TARGETNAMESPACE;
use Traversable;
use Zend\Mvc\Router\Exception;
use Zend\Mvc\Router\Http\RouteInterface;
use Zend\Mvc\Router\Http\RouteMatch;
use Zend\Mvc\Router\Http\Literal;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\RequestInterface as Request;
class MyRouterLiteral extends Literal {
public function match(Request $request, $pathOffset = null) {
if (! method_exists($request, 'getUri')) {
return null;
}
$uri = $request->getUri();
$path = $uri->getPath();
if ($pathOffset !== null) {
if ($pathOffset >= 0 && strlen($path) >= $pathOffset && ! empty($this->route)) {
if (strpos($path, $this->route, $pathOffset) === $pathOffset) {
return new RouteMatch($this->getDefaults(), strlen($this->route));
}
}
return null;
}
if ($path === $this->route) {
return new RouteMatch($this->getDefaults(), strlen($this->route));
}
return null;
}
private function getDefaults() {
$aux = explode('\\', $this->defaults['controller']);
$last = array_pop($aux);
array_push($aux, '[CUSTOM_INSTANCE_NAME]');
array_push($aux, '[CUSTOM_INSTANCE_NAME]'.$last);
$result = $this->defaults;
$result['controller'] = implode('\\', $aux);
return $result;
}
}
To address all cases I had to create a second custom router (for segment routes) which follows the same rules and can be easily derived from the above code.

Phalcon loading helper file library

I have created a library that which will load a php file (which may contains users custom functions in it...) you can either call it from bootstrap also from the controller. if file does not exists it will display the error msg. Thing is am i doing it in the currect way?
If i did miss any thing point me out.. Thanks
Helpers is the folder where users can put php files
app/
controllers/
models/
helpers/
library/
views/
In "library/" Folder a php file named "helperfile.php"
class helperfile extends Phalcon\Mvc\User\Component
{
var $helper_Folder = '../app/helpers';
var $files = array();
public function __construct()
{
}
public function initialize()
{
}
public function include_file($files, $run = true)
{
if (!is_array($files))
$files = array($files);
foreach ($files as $file)
$this->files[$file] = $file;
if ($run)
$this->load();
}
public function beforeDispatch()
{
$this->load();
}
private function load()
{
if (empty($this->files))
return false;
foreach ($this->files as $file) {
$file = trim($file) . '.php';
if ($this->is_file_exists($file)) {
require $this->helper_Folder . '/' . $file;
}
}
}
private function is_file_exists($path)
{
$full_path = $this->helper_Folder . '/' . $path;
if (!file_exists($full_path)) {
$this->flash->error("Helper File Missing: " . $full_path);
return false;
}
return true;
}
}
// to auto load file on every page through the bootstrap ("public/index.php")
$di->set('dispatcher', function () {
//Create/Get an EventManager
$eventsManager = new Phalcon\Events\Manager();
/*
* Load Custom function files which are in the helpers folder
*/
$loadHelper = new helperfile();
$loadHelper->include_file([
'calling_from_bootstrap_1',
'calling_from_bootstrap_2'
],false);
$eventsManager->attach('dispatch', $loadHelper);
$dispatcher = new Phalcon\Mvc\Dispatcher();
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
});
// To load it from controller
$loadHelper = new helperfile();
$loadHelper->include_file([
'calling_from_theController'
]);
That looks like it shoould work, but I think you underestimate the amount of work Phalcon can do for you.
An example of what is in the helper files would be useful. For the sake of this example I will assume that that it is like this:
app/
helpers/
ProductHelper.php
and in ProductHelper.php
class ProductHelper{
// code here
}
In your bootstrap where you have the loader you define your directories
$phalconLoader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$phalconLoader->registerDirs(
array(
$phalconConfig->application->controllersDir,
$phalconConfig->application->modelsDir,
// path to helper dir here
)
)->register();
and then in your controller
public function productAction(){
$productHelper = new productHelper();
}
That should work. It is less code, so is simpler should run a bit faster (using phalcon's built in code rather than writing some php will always be faster)
If the code in the helpers is not in classes, or not named the same as the filename, then it probably should be. Makes things a lot simpler.
Di Enabled Version
class ProductHelper extends \Phalcon\DI\Injectable{
public $config;
public function myFunction(){
$this->config = $this->getDI ()->get ('config');
}
}
and in the controller
public function indexAction()
{
$helper = new ProductHelper();
$helper->setDI($this->getDI());
$helper->myFunction();
}
Alternatively when creating your DI
$di->set ('productHelper', function () use ($config, $di) {
$helper = new ProductHelper();
$helper->setDi ($di);
return $helper;
});
and in the controller
public function indexAction()
{
$helper = new ProductHelper();
$helper->myFunction();
}

Categories