This question was asked in 2010. I am seeing a related problem but the recommended solutions from 2010 don't fix it.
I am using PHPExcel v 1.8.0 (March 2014)
The suggestions made on the original reply have been incorporated and the rest of the system still works normally, for example I have an init.php file that is brought in for every scrip which includes the following as suggested in an earlier post:
function myAutoload($Class)
{
require_once 'Classes/' . $Class . '.php';
}
spl_autoload_register('myAutoLoad')
All {classes.php} files are in the Classes/ folder off the document root including, of course PHPExcel.php. The PHPExcel folder is also contained in the Classes/ folder.
I have tried various ways of spinning up PHPExcel, including the usual
$spreadsheet = new PHPExcel;
As an alternative I also tried defining a Spreadsheet class
Class Spreadsheet extends PHPExcel {.... }
They all produce the same error as cut and paste into the above
I have successfully ported over the remainder of the processes in the application from a procedural style to object orientated system, and it has been well worth the weeks that have been spent on it. This last hurdle with PHPExcel however has got me foxed!
Any suggestions would be appreciated
Modify your autoloader to return a false if it can't load the specified file:
function myAutoload($Class)
{
if (file_exists('Classes/' . $Class . '.php')) {
require_once 'Classes/' . $Class . '.php';
return true;
}
return false;
}
That way, autoloading will from through your own autoloader and execute the next autoloader in the "queue" (the PHPExcel autoloader) if it doesn't find the requested file through your own autoloader. If you don't return a false the SPL autoloader handler won't bother working through any other "queued" autoloaders
Related
I have been trying to load the various classes associated with PhpSpreadsheet, but am encountering many problems.
I have followed many postings and implemented spl_autoload_register using the following code:
function my_autoload($classname) {
$fullclassname = $classname . '.php';
include $fullclassname;
}
set_include_path(get_include_path() . PATH_SEPARATOR . '/var/www/html/mywebsite/includes/PhpOffice/PhpSpreadsheet/');
spl_autoload_register('my_autoload');
use PhpOffice\PhpSpreadsheet;
Unfortunately, all I every get is 'Class not found'.
I've discovered that a limitation of spl_autoload is that it requires everything to be in lower case. As I understand it, this would require every directory name, file name, Class name and Namespace definition within PhpSpreadsheet to be modified. Not a viable long term solution.
Another alternative is to hard-code include statements for each .php file within PhpSpreadsheet. Again, not a viable long term solution.
Is there another option?
After a little bit of research and have been unable to locate a solution to my problem. I am utilizing an API that is namespaces that I downloaded via composer. The API has it dependences that I allow composer to manage and autoload for me. Separate from this I have about 10 classes that I have autoloaded with utilizing php's spl_autoload_register. Recently, I started mixing the classes to finish up part a project and the whole thing has gone to crap. My custom classes cannot use the composer classes and visa versa. Is there a method I can use to autoload classes that are in two separate folders and that are loaded with two separate outloader.
Here is the code that I currently use. The vender/autoload.php is no different then your typical composer autoloader. Thanks for any assistance.
require 'vendor/autoload.php';
require 'functions/general.php';
require 'include/mailgun.php';
function my_autoloader($class) {
require 'classes/' . $class . '.php';
}
spl_autoload_register('my_autoloader');
Well, actually composer utilizes spl_autoload_register, so answer is 'yes', they can. The autoloading mechanism is supported by autoloader stack - basically, if class didn't appear in runtime after one autoloader has been run, next one is used, until stack runs out of autoloaders and PHP reports an error about a class it can't find. Every spl_autoload_register call basically adds new autoloader, so there may be plenty of autoloaders in memory. The main point of this story is autoloader that can't load class does nothing, the autoloading block of code simply ends with no action taken so next autoloader may take responsibility of class loading. The only thing you need to implement is check in your autoloader that it can handle current class loading (checking that file exists before requiring it is enough, though you should think about possible directory nesting in case of namespaces), and everything should work smooth in future:
function my_autoloader($class) {
$path = sprintf('classes/%s.php', $class);
if (file_exists($path)) {
require 'classes/' . $class . '.php';
}
}
After further research due to ideas that the both #Etki and #Sarah Wilson gave me I came up with the following solution. Thank You both for your input.
require 'vendor/autoload.php';
require 'functions/general.php';
require 'include/mailgun.php';
function autoLoader ($class) {
if (file_exists(__DIR__.'/classes/'.$class.'.php')) {
require __DIR__.'/classes/'.$class.'.php';
}
}
spl_autoload_register('autoLoader');
Hint: I added the __DIR__ to the beginning of the file paths inside the autoLoader function.
If this is for a small project where you are including files from two or three folders you can use a simple if statement.
function my_autoloader($class) {
if(file_exists('functions/'.$class.'.php')){
require 'functions/'$class.'.php';
} else if(file_exists('vendor/'.$class.'.php')){
require 'vendor/'.$class.'.php';
} //add more as needed
}
spl_autoload_register('my_autoloader');
For larger applications, I recommend naming your classes files and your classes for what they are or do, and have them in a specific folder by their names Example: controllers/userController.php for userController class functions/generalFunctions.php generalFunctions class then you can check the names and if it has controller then you include it from the controllers folders. Create an array within the my_autoloader function or in a separate file like.
loadMap.php
return [
'controller' => 'path/to/controllers/',
'function' => 'path/to/functions/',
'helper' => 'path/to/helpers',
'etc' => 'path/to/etc/'
]
filewithautoloadfunction.php
function my_autoloader($class){
$loadMap = require 'path/to/loadMap.php';
foreach($loadMap as $key => $path){
if(stripos($key, $class){
require_once $path.$class.'.php';
}
}
}
spl_autoload_register('my_autoloader');
I am trying to add the Imagine image library into a Codeigniter application, but this is the first time I have ever encounter the "namespace" and "use" concept which I just don't get. Most Libs usually need an include, require etc... to make them work with your framework but I am having a hard time trying to implement this "namespace", "use" approach.
Now how far did I get, well I downloaded the Lib, put the Imagine folder in my libraries folder in CI where I have another image Lib call wideimage which I had no problem adapting to CI. I try to be creative and and loaded the library files just like any regular library file is loaded in CI.
And thats where the problem began, I started getting a lot of errors like class is not found got the error line and right away I thought it may need that other file that has that class now that work for some of the errors that it kept on giving me but its like every time a new lib file is loaded another error comes up and some errors just won't go away even if the file with the main class is present.
Now I did found an article on how to set an SPL auto load and I got the following code
set_include_path('/application/libraries/Imagine' . PATH_SEPARATOR . get_include_path());
function imagineLoader($class) {
$path = $class;
$path = str_replace('\\', DIRECTORY_SEPARATOR, $path) . '.php';
if (file_exists($path)) {
include $path;
}
}
spl_autoload_register('\imagineLoader');
But never got it to work, in this case it gave me an error of CI classes or files where not being found.
Now again to my questions is there a way to implemet this Imagine image library into Codeigniter?
To either load it through the regular library loader or through an autoload file?
Something like this;
class Test extends CI_Controller {
function __construct()
{
parent::__construct();
$this->load->library('imagine');
}
public function index()
{
// Do some cool things with the image lib functions
}
}
Well I would really appreciate anyone's help on this in the mean time I will keep on looking around the web to see if I can find an answer.
Anyway after a day of looking I finally found a way to do it, and thank you simplepie feed parser I knew I had seen similar code in the past.
Anyway I actually looked over at the simplepie autoloader.php file which loads the classes to use simplepie and I just did some small adjustments to the code to be able to use Imagine Lib in Codeigniter.
So here are the steps and code:
1 download the Imagine Library at:
https://github.com/avalanche123/Imagine
2 Copy the Imagine folder into your CI application libraries folder: application/libraries
3 Create a file and call it imagine_autoload.php
4 add the following code to the imagine_autoload.php file
set_include_path('/application/libraries/Imagine' . PATH_SEPARATOR . get_include_path());
function imagineLoader($class) {
$path = $class;
$path = str_replace('\\', DIRECTORY_SEPARATOR, $path) . '.php';
if (strpos($class, 'Imagine') !== 0)
{
return;
}
include_once $path;
}
spl_autoload_register('\imagineLoader');
Now to the fun part on your controller do the following:
require_once('./application/libraries/imagine_autoloader.php');
// Here you can use the imagine imagine tools
use Imagine\Image\Box;
use Imagine\Image\Point;
class Testing extends CI_Controller {
function __construct()
{
parent::__construct();
}
function index($offset = 0)
{
$imagine = new \Imagine\Gd\Imagine();
$image = $imagine->open('/path/to/image.jpg');
$thumbnail = $image->thumbnail(new Imagine\Image\Box(100, 100));
$thumbnail->save('/path/to/thumnail_image.jpg');
}
}
Now go an look at where you saved the new image and you will find a new image that has been re size.
Hopefully someone will find this useful.
I am having trouble implementing a particular class in PHP. I want to use Anthony Ferrara's RandomLib library in my Zend Framework application (you can find it here.)
I've been programming in PHP for a few years now, so I know my way around it for the most part. But I have to admit that I'm kind of clueless when it comes to using classes that implement namespaces. Here's what I've got in my code:
public static function generateToken()
{
require_once 'RandomLib/Factory.php';
$factory = new \RandomLib\Factory;
$generator = $factory->getMediumStrengthGenerator();
return $generator->generate(16);
}
Unfortunately, I'm getting the following error:
Fatal error: Class 'SecurityLib\AbstractFactory' not found in C:\xampp\php\includes\RandomLib\Factory.php on line 30
Like I said, I really have no idea what's going on here. I don't know if I'm supposed to use some kind of use statement in my class or not.
With autoloader with ZF 1.*, asuming you put your factoru into application_name/libs/RandomLibFactory.php as RandomLibFactory class it should look like this:
public static function generateToken() {
$factory = $locator = new RandomLibFactory();
$generator = $factory->getMediumStrengthGenerator();
return $generator->generate(16); }
For anyone whom spent lot of time and didn't find a clue, tearing his hairs apart and hitting the wall to death:
you need to have an autoloader as in "bootstrap.php" in the folder "test/", to manage every namespace... or you need to link every file in the folder which is not very smart. See spl_autoload_register in php.net
you just downloaded RandomLib, which depends on another library (the author didn't mentioned it): so you need SecurityLib (it has the same folder structure: copy what is inside "lib/" into the other "lib/" folder.
example of autoloader for a script calling from the root folder "RandomLib-1.1.0/" (see that 'lib' in the $path ?):
spl_autoload_register(function ($class) {
$nslen = strlen(__NAMESPACE__);
if (substr($class, 0, $nslen) != __NAMESPACE__) {
//Only autoload libraries from this package
return;
}
$path = substr(str_replace('\\', '/', $class), $nslen);
$path = __DIR__ . '/lib/' . $path . '.php';
if (file_exists($path)) {
require_once $path;
}
});
now you are set and can use classes freely without worrying about including or requiring files.
$factory = new RandomLib\Factory;
$generator = $factory->getLowStrengthGenerator();
//$generator = $factory->getMediumStrengthGenerator();
//$generator = $factory->getHighStrengthGenerator();
$randomStringLength = 16;
$randomStringAlphabet = '0123456789#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/';
$randomString = '';
for ($i=0;$i<10;$i++){
$randomString = $generator->generateString( $randomStringLength , $randomStringAlphabet);
echo $randomString.'<br>';
}
I too tore out many hairs, before I found the solution for my Windows machine.
I downloaded the Windows version of Composer (which I had barely heard of let alone used).
I used it to install RandomLib (as shown in the Install section of the instructions - use a command box in Windows)
This generated a vendor folder containing a composer folder an ircmaxell folder and an autoload.php file; these I uploaded to a suitable place in my website The vendor directory includes both the random-lib and the - required - security-lib libraries.
In the program in which I wanted to generate random text I included that autoload.php (preceded by suitable directory pointers)
Then I was good to go to create a factory, generator and string as shown in the library's instructions
I have a strange problem I can't figure out. I'm using PEAR to send mail from a PHP page. The Send_Mail class is working (sending mail using SMTP), but I'm getting this strange warning associated with my autoloader.
Warning: include(classes/LOGIN.php)
[<a href='function.include'>function.include</a>]:
failed to open stream: No such file or directory in
C:\xampp\htdocs\mysite\initialize.php on line 46`
In my initialize.php file, I have this:
function autoloader($class) {
include 'classes/' . $class . '.php';
}
spl_autoload_register('autoloader');
And in my header.php file I am loading several PHP classes for the site:
// autoload PHP classes for site
autoloader('Navigation');
autoloader('Validation');
The error referes to a LOGIN class which I don't have. But I searched my entire site folder, including php and found these two lines in C:\xampp\php\PEAR\Net\SMTP.php:
/* These standard authentication methods are always available. */
$this->setAuthMethod('LOGIN', array($this, '_authLogin'), false);
$this->setAuthMethod('PLAIN', array($this, '_authPlain'), false);
When I comment out the line containing LOGIN I get the same warning but for PLAIN and when I comment out both lines, the warnings go away (but then SMTP authentication fails).
Why is this happening?
UPDATE
Here is my new autoloader:
function autoloader($class) {
if (file_exists('classes' . $class . '.php')) {
include 'classes' . $class . '.php';
}
}
When I echo 'classes' . $class . '.php', though, I get this:
classes/.php
And then if I change it back to not use the file_exists it works, but the echo still shows classes/.php
I'm not sure what version of Net_SMTP you're on, but the setAuthMethod function takes as a parameter various different types of structures - method names, classes, objects, callables, etc.
Since PHP is dynamically typed, SMTP.php in Net_SMTP has to do a lot of checking on that object in order to determine what type of object it is. As part of that, it tries to determine if 'LOGIN' is a class name, which is invoking your autoloader.
The solution is to perform a file_exists in your autoloader before trying the include, but of course if your include path is complex in any way you're basically setting yourself up for headaches. Anyone who has dealt with writing a comprehensive autoloader knows your pain.
I reverted back to a simple autoloader and things seem to be working fine:
function autoloader($class) {
include 'classes/' . $class . '.php';
}
spl_autoload_register('autoloader');
Thanks for suggestions.