I recently got a email from a plugin developer, with regards to him having compatibility issues with one of the plugins I had developed. It turned out that both our plugins used a popular library called PclZip for adding archiving features. Due to the compatibility issue, accessing his plugin would cause a fatal PHP error saying that the PclZip class cannot be re-declared, when both our plugins were activated.
The compatibility issue arose because of two things;
- A mistake on his part while checking for existence of class objects in the code.
- A mistake on my part of using custom libraries, instead of using those provided by WordPress core.
Here is a code snippet used to check for class existence.
if(! function_exists(‘class_name’)) {
require_once(‘myclass.php’);
}
$object = new class_name();
The above code is wrong, since:
- Class names cannot be accessed as functions.
- The internal methods of a class are not available for checks, unless one decides to instantiate the class and use the method_exists instead.
The correct way to check if a class exists or not can be seen in the following code.
if(! class_exists(‘class_name’)) {
require_once(‘myclass.php’);
}
$object = new class_name();
This change in code actually solved the compatibility issue, but I would like to discuss a bit further on why one should rely on libraries provided by WordPress core instead of using their own custom libraries. The fatal error could have been avoided, if my plugin made use of the the library files from core WordPress, instead of using custom libraries included with my plugin.
If both our plugins had relied on the library files provided by WordPress, the require_once directive would not have re-evaluated the โsame fileโ again, thus avoiding the duplicate class issue. Earlier versions of WordPress did not include many popular libraries, and many plugins include those libraries to provide backward compatibility. If you have to provide backward compatibility for your plugins, be sure to add in a WordPress version check so that you can rely on your own libraries, only when a version of WordPress does not provide it, doing this will certainly do away with having to tackle the compatibility issues caused by plugins using different files for the same libraries.
Update: Including files for backward compatibility can be accomplished by using the following code.
if(!class_exists(‘PclZip’)) {
if(file_exists(ABSPATH.’wp-admin/includes/class-pclzip.php’)) {
require_once(ABSPATH.’wp-admin/includes/class-pclzip.php’);
}
else {
require_once(‘/path/to/your/lib/class-pclzip.php’);
}
}
It is also a good practice to include the classes only when you require them, and later destroy the object by using the unset() method. This is a non-exhaustive resource for tackling compatibility issues between plugins, and I will try and research more on other things that can help avoid these issues and keep informing you about them.
If you have your own advice about avoiding such issues, please do share them with us.
Further reading from PHP documentation:
Great article!
You actually hit on a great point with using
unset
to destroy it when you’re finished with it. I actually don’t do that in my plugin, but I should. I’m going to add that for the next release I think.I think it’s important that all plugin developers code their plugins in such a way that they will not clash with each other. Otherwise you end up with a big mess. My plugin could probably do more to help prevent clashing. I just need to learn more. It is my first plugin so I’m still learning as I go.
Anyway, great article!
Good post. I’ve run into many issues with my plugin and Wordbook conflicting. I’ve made sure that Fotobook only includes the Facebook API library whenever it uses it. However, Wordbook makes use of the same library more frequently and often tries to redeclare the Facebook API classes. You mention unsetting the object, but in my case the problem is that both plugins are declaring the same class. So undeclaring the class would be more appropriate. But to my knowledge that isn’t possible.
great article, although I am not a programmer by any means, I udnerstand what you are talking about and have personally had issues with different plugins, which were loading the same libraries, causing conflicts, which is pretty hard to solve for a user, you need to get in touch with both plugin developers and hope they can help.
Hopefully more plugin developers will read this article ๐
Keith, I have not seen the code in the custom library but I think there is more confusion here than you had discussed here.
In object oriented programming, every class will normally have a constructor and the constructor will have the same name as the class. That was the case until php 5.0 introduced __construct() as the constructor name.
That might have been the reason.Has the author of the custom library not updated it for PHP 5.0? I am guessing that the plugin author, who contacted you, must have got this error on php 5.0.
But this is a problem with php as a language.They seem to be making such drastic changes in the language, putting the developers to hardships ๐ We do not see these in other real object oriented programming languages like Java…PHP has a long way to go…
But the custom library author would have done well to check it as a class rather than as a function…But when he developed it for a versions earlier to php 5.0, he would not have anticipated such a drastic change in version 5.0…if the original author is no longer supporting it then it is no fault of his.I will blame it on PHP.
I would also like to add that this is sometimes the case even with wordpress..it is more important to advertize the deprecated functions and the replaced functions, whenever a new wordpress version is released.This will help the plugin authors to update their plugins easily.
Ok…
if he had instatiated the class and checked the function inside the class with a methos-exists() call, I guess he would still have been safe…
Keith, it would be nice if you could mention the function name and the line of code in the library that caused this error? Is it a function inside a class?
This is more interesting really…i don’t think it is the if loop that is causing the issue.Wouldn’t require_once() ensure that the code from the file is included only once.
I am guessing that it is the object creation line(done twice) that is causing the incompatibility issue…
Like I described require_once will evaluate different files and not re-evaluate the same files. So if two plugins are using their own libraries require_once will throw a fatal error. This issue can be tackled by using the if condition.
On the other hand multiple Object creation will never give you a error, they are unique of each other.
Oh yes, i somehow missed the note on plugins using their own libraries in this case..you are right…
Just to add that creating a new using the new keyword would throw an error if the class is not found, so it becomes essential to use the if condition, to safely check if no other plugins have already used the library. Method exists can be used when you are trying to check for functions that were deprecated or when you are trying to check for backward compatibility of a library.
Just to add that creating a new using the new keyword would throw an error if the class is not found, so it becomes essential to use the if condition, to safely check if no other plugins have already used the library.
If both the plugins are using the same library, why should it be ensured that no other plugins have already used the library? What is wrong if they use it, as they are anyway using require_once()….
There is a genuine need for a tutorial (or whatever) going into painful details about plugin interactivity and compatability, to include the use of common libraries (like jQuery) across plugins and the user’s own homebrew coding (adding actions into wp_header).
Steve,
Very true. That would be very helpful and eliminate a lot of messy code. I think most plugin coders just start off doing whatever they can to make it work without realizing some of the systems that are in place to streamline things and avoid some of these conflicts.
I know that’s true for me. When I started on my plugin I was just out to make it work. Then I discovered that there was much more I had to do to make it play nicely.
By the by, I’m the person who E-mailed Keith. It was about my plugin Easy Admin Color Schemes which also uses the PclZip function a little bit. Just thought I’d name the anonymous “plugin developer”. ๐ So, any of you who are interested in looking deeper can have a look at my code. A warning though: It may not be pretty. It’s my first plugin. ๐
I don’t really blame plugin developers, though… because most plugins start out as an individual site-owner’s need to “do something” that he or she can’t find an existing plugin for. So initially you go off and “just make it work”. Later on you may offer your plugin up for the masses… who then manage to find 100 ways to break it! ๐
I know for myself that I’ve been calling the jQuery code from Google code… and then running it in my wp_footer() for whatever I use it for (sIFR, etc.). I know that some people, instead, load jQuery through wp_enqueue_script — but I know little to nothing about this, other than it’s probably a more correct method. ๐ I DO know that another method is to load jQuery DIRECTLY from the WordPress core (which even allows for a query value specifying which version of jQuery).
All I know is, that my own code fights with plugins just as well as the plugins fight each other. Recently Lightbox2 (a tremendous idea) blew away my homebrew jQuery code. The Google code hosted IE-7.js (which fixes IE6 neatly and cleanly) blew away my Kimili Flash Embed plugin. It’s like I can’t win. ๐
There’s got to be a better way of exposing core code and common libraries… and viewing plugin dependencies. Should this maybe be part of the WordPress admin plugin page? Like a prereq/library field or something?