How to handle the conflict in multiple autoloaders - php

I am using _autoload in my system, and I need to import a library that has alot of classes, it uses _autoload function to auto-load its classes.
unfortunately once I call this library the code is calling my classes with a wrong path.
does anyone have any idea how can i solve this issue?

As mentioned in the comments section, you could just register your autoload function especially for your namespace. Taken from the php docs, here is one example:
<?php
namespace Foobar;
class Foo {
static public function test($name) {
print '[['. $name .']]';
}
}
spl_autoload_register(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0
new InexistentClass;
Read up on PHP Namespaces to fully understand how this works.

Related

PHP import classes with use keywords

I don't use so far PHP use word, but must now... :)
index.php content:
require_once 'Classes/MainClass.php';
$obj = new Main();
echo $obj->test();
Classes/MainClass.php
<?php
use AdminFrontEnd;
class Main {
function test(){
return new AdminFrontEnd("debug");
}
}
AdminFrontEndClass.php content:
<?php
class AdminFrontEnd {
function __constuctor($test){
echo $test;
}
}
and final, following error:
Fatal error: Class 'AdminFrontEnd' not found in Classes/MainClass.php
on line 10
As per comment from #deceze, you will either need to explicitly import the additional class, using a require statement, or autoload.
The use statement is for aliasing a class, and as #deceze said, can be used to pull in a class from a different namespace, or to avoid a class conflict.
Having a class called 'Main' may not be ideal. Is it a singleton, or will there be multiple 'Main's? Maybe this class would be better named 'App'.
In the longer term you will want to learn about using namespaces, so that if you use other people's classes and plugins, you won't have conflict. I've added a solution, and also some broader info below.
To get you off the hook:
Classes/MainClass.php
<?php
require_once 'Classes/AdminFrontEnd.php';
class Main { /* etc... */
Further reading I would recommend:
Examples for creating an autoload:
http://php.net/manual/en/language.oop5.autoload.php
You'll probably want to learn about namespaces too:
http://php.net/manual/en/language.namespaces.php
I also highly recommend reading about interoperability coding standards. It's a lot to take in to begin with, but it will help you understand the logic behind using namespaces, and autoloaders.
http://www.php-fig.org/

Codeigniter Custom Libraries and Namespaces

I have been creating custom libraries for a project that i've been porting over into the CI framework and I ran into an issue where certain classes have identical names.
To circumvent this issue, I tried implementing namespaces to no avail. I've been doing research and I know in the past this may not have been possible but with the newer version of PHP, I was wondering if there was a way to do this or if I was doing it correctly.
CI Version: 2.1.4
PHP Version: 5.4.12
Here is a demo of my setup:
application/libraries/class1.php
<?
class class1{
public function __construct()
{
$CI =& get_instance();
$CI->load->library('foo/class2.php');
}
}
?>
application/libraries/foo/class2.php
<?
namespace foo
class class2{
function bar(){
}
}
?>
When I run my CI application, I will get the following error:
Non-existent class: class2
Thanks for any help.
From what I've found, if the library file doesn't have
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
as the first line of code it won't load the library.
But then the namespace declaration needs to be above that.
CodeIgniter was written for PHP4 whereas namespace is PHP5.
There's more information in this thread: Namespace in PHP CodeIgniter Framework
Codeigniter does not support namespaces in 2.x and 3.x, what I would usually do especially with 3rd party libraries is load them in manually. Using your example, I would do:
// you can still manually load in libraries like this
require_once(APPPATH.'libraries/foo/class2.php');
class class1 {
public function __construct()
{
$CI =& get_instance();
// instantiate the class2 and make it available for all of class1 methods
$this->class2 = new foo/class2();
}
}
Just because it's a framework doesn't prevent you from using core php functionality, most people forget that you can still do normal php methods to achieve the same results.
This issue arose in a personal project while attempting to use some third-party libraries.
To get around it (without modifying the source files), I made a "bootstrap" class that loaded and extended the core library:
<?php
require_once(APPPATH.'libraries/foo/class2.php');
class class2 extends foo\class2 {}
This "bootstrap" class can then be loaded and used as if it were the extended one:
$this->load->library("class2");
$this->class2->bar(); // same as foo\class2->bar();
The issue is that 'load' doesn't take into account namespaces as far as I know.
which means that load('foo/class2') will look for the folder 'foo' inside the libraries folder.
you include the files normaly, when you create a new object you use the 'foo/bar'.
I'm not if the load class supports that though, You might need to simply create a new object manually(which is what the load class does anyway, it includes the file and creates a new object).
I'll quote an answer from Alex.
I know I've answered this question before I just can't find where and don't know what to search. So here it is: Codeigniter can only load single php file libraries (excluding drivers which is a different thing entirely). To load this kindof library (namespaced) you have to use something like: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md (class example).
Let's call it Autoloader_psr4 and save it in libraries (modify the class declaration to match this name verbatim (e.g. Autoloader_psr4). Remove the namespace declaration in the class so it looks like: https://pastebin.com/NU8Rbp7Y
Let's also move all the files in src/randomorg/ or src/foo to just be in a folder in third_party called RandomOrg or foo e.g. application/third_party/RandomOrg or application/third_party/foo. Your folder should look like the contents here: https://github.com/defiant/randomorg/tree/master/src/randomorg
Usage:
$this->load->library('autoloader_psr4');
$this->autoloader_psr4->register();
$this->autoloader_psr4->addNamespace('RandomOrg', APPPATH . 'third_party/RandomOrg');
$random = new \RandomOrg\Client(); // or whatever...

Is it possible to autoload static libraries using spl_autoload_register?

I am wondering is it possible to auto load static class, as like creating object to dynamically autoload library ?
I have done most of the part of php autoloader but really need to tips to autoload static libraries for which I don't want to create object.
Is there anyone have solution ? Please post or else give me best idea to develop the same.
Thanks
Yes SPL Autoloader will load classes and interfaces. Once the autoloader is triggered you can use any reference to an auto-loadable asset to trigger the load
My_Special_Class::SOME_CONSTANT
will trigger a load as well as calling or referencing any visible static method or property.
In fact exploiting this is one way to trigger the auto_loading of namespaced functions. Define a class file like this.
namespace My\Namespace;
abstract class Functions{
const LOADED = true;
}
function func1(){}
function func2(){}
function func3(){}
And in your code when you need the functions defined in My\Namespace simply
if (\My\Namespace\Functions::LOADED){
func1();
func3();
}
The reference to the abstract class triggers the autoloader to include the file that defines the functions.

Use namespace in global context with autoloader

Due to an external library I have to use namespaces. Since I havn't used namespaces before I realised using a namespace won't work with my __autoload(). The code below will say
Failed to load class Foo\Bar\NamespaceClass, please update the autoloader!
How may I fix this? The Foo class is just a wrapper around the external library.
// This is my autoloaded class file
use Foo\Bar\NamespaceClass;
class Foo
{
public function Bar()
{
$namespaceClass = new NamespaceClass();
}
}
// This is a separate file calling my class "Foo" from global namespace
$myAutoloadedClass = new Foo();
$myAutoloadedClass->Bar();
I don't think you understand how namespaces work. I recommend you to read articles about that, for instance this one on nettuts+.
Furthermore, I recommend you to use the PSR-0 standards. Almost all 3rd-party libraries follow that and they come in with a autoloader which you can use directly.
At last, you said you use an external library. Have you take a look at composer? That a really great tool to help you autoloading, updating and using external libraries. I recommend you to watch the great screencast of KnpUniversity: "The Wonderfull World of Composer"
You should update the autoloader.

Is it bad to include all the Namespaces and access Classes with just their class name in PHP?

Recently I have started to play around with Namespaces in PHP, I am not a fan of the chosen Namespace separator / (as most others have a mutual feeling) /
Below I have a very basic/simple example of using Namespace in PHP.
I have a Registry.class.php file that has a Registry class that is in the Namespace Library
I also have the file Controller.class.php below that has a Controller class that is in the Namespace called Project
Now in this Project Namespace I need access to the Registry object that is in a different Namespace, Library So I use use Library\Registry to Import that Namespace
With that done, I am able to simply access my Registry class like this...
$this->registry = new Registry;
Now if I had not used use Library\Registry then I would have to access it like this
$this->registry = new /Library/Registry;
So this is where my question begins.
For this simple example I am just bringing in the Registry class, in a real project, imagine several other classes and namespaces being brought in, So I would be using
use Library\Registry and use Library\SOME OTHER CLASS and use Library\YET ANOTHER CLASS etc...
I can then operate on the Objects/classes as if they were in this namespace to begin with so instead of pre-fixing the class name with its appropriate Namespace name, I simply just instantiate the class by its name ( new Registry;) instead of new /Library/Registry;
I would like to know if this is considered bad practice or not? It greatly simplify's things and makes the code look cleaner IMO, but if there is anything bad about this method I would like to know before I write a lot of code using this method. Should I be pre-fixing my classes when I instantiate them with their namespace INSTEAD of importing them with the use /Path/to/Namespace/Classname ?
Please share your knowledge with me, I realize it will work either way but I want to make sure. Example classes and namespaces are added below:
Controller.class.php
<?php
namespace Project
{
use Library\Registry;
class Controller
{
public $registry;
function __construct()
{
include('E:\Library\Registry.class.php');
$this->registry = new Registry;
}
function show()
{
$this->registry;
echo '<br>Registry was ran inside testcontroller.php<br>';
}
}
}
?>
Registry.class.php
<?php
// Registry.class.php
namespace Library
{
class Registry
{
function __construct()
{
echo 'Registry.class.php Constructor was ran';
}
}
}
?>
One of the primary purposes of namespaces is to prevent name conflicts in large code bases and across shared code and imported libraries. If you're not having name conflict issues, then I don't necessarily see anything wrong with using each class. If you find yourself doing this for all your classes, however, then I would question why you're using namespaces in the first place. This would only seem to make sense to me if your code was going to be used as an API or library by someone else.

Categories