If i've different version of same third-party library ( or class ) that have of course same namespaces and class names. Is there a way to include them in same project avoiding name collisions?
Another case for this issue happens when we've a modular project where components are developed separately . So we can have different modules that includes same external library file in their own folder, but of course when modules will be loaded , we have a class collision.
in this article Loading multiple versions of the same class
an user suggests to use this code:
namespace old {
include /lib/api-1.0/library.php;
}
namespace foo {
include /lib/api-2.0/library.php;
}
$oldlibary = new old\Library();
$newlibrary = new foo\Library();
but of course it doesn't work. Classes collides anyway because they are declared gobally instead of vars.
So..is there another solution that is not hand-edit all the namespace of libraries to include?
thanks in advance
This is a very common problem in modular systems. In PHP you could try to solve it with very bad hacks (eval, file_get_contents, str_replace), but you would loose a lot of usefull tooling support (backtrace, debugging, op code cache, precise error reporting, just to mention a few).
The usual way to approch these problems is to use some kind of dependency management. E.g. in java maven is used most times, in scala it is maven or sbt and php guys would normaly use composer (never used this one, so I'm not completely sure whether it is good or not and whether it even supports what you need).
These tools usualy have some kind of algorithm to detect and solve typical version conflicts. However this will only work if two conflicting versions are compatible (or at least the part you are using is compatible). They will either select one of the provided versions, select some version in between (sometimes very strange) or let you decide which version to use. But of course, they also cannot solve problems in which you will definitely require both versions within the same namespace.
Generally said, the easiest way is to allways use the same library or module version company wide or at least application wide. The tools above will help you with that.
Sorry, to not help you with your concrete problem, but I hope some of the provided keywords will be of some use for you.
Related
I've been tasked to migrate an old PHP4.3 site (using CVS version control) to a more modern 5.2 install (lower version number for compatibility issues) on a shared GoDaddy server. I've gotten through most of the issues, but this particular one is a tough nut.
Inside the administration view, there is an export to excel function which uses the Spreadsheet_Excel_Writer (0.9.3) PEAR package. However, this line keeps throwing a fatal error:
aggregate( $sheet, 'Spreadsheet_Excel_Writer_Sheet_Patch' );
where $sheet is defined by
$sheet =& $xls->addWorksheet( 'Customer Data' );
My issue is that aggregate no longer exists in PHP5, and I cannot install runkit as I do not have root permission to execute the pecl install command on the server.
I'd rather not have to rewrite the existing functionality, so is there a drop-in replacement for aggregate that I can install without requiring root permissions?
With regard to the Excel library you're using, you will need to upgrade that to a version that supports PHP5, or else migrate to an alternative library. There are several Excel libraries available which do support recent PHP versions, so you should probably investigate those.
I won't recommend any specific library now, as I haven't worked with any of them for a little while and so my recommendation may not be the best. And in any case, your needs may be different to mine. Instead, simply googling for 'php excel' will give you plenty of results to help you find a library to suit you. You will obviously need to rewrite your code where it uses the old library so make it work with whatever new library you choose, but that will be infinitely easier than trying to make the old library itself work. (also, newer libraries will support newer excel versions, which is probably quite important; things do move on)
I certainly wouldn't recommend trying to keep using the existing library; it's clearly written for PHP4, and would likely be a very difficult task to bring it up to date.
You mention runkit: that wouldn't likely be a good solution here even if you were able to use it. For something closer to what the aggregate() function does, you might want to investigate the Reflection class, which allows some similar class- and object-level trickery, but in general well-written code shouldn't need that kind of thing anyway (it may have done in PHP4 days, but much less so today).
Another alternative to aggregate() might be the Traits feature in PHP 5.4 and up. This can give some of the multi-inheritance functionality that aggregate() was sometimes used to simulate. Obviously, you'd need to upgrade to 5.4 for this though, and the actual code you'd write would be quite different.
I'm writing a Wordpress plugin, so it's going to be used by different users and different PHP versions. The problem is that I found that some of the functions (like json_encode) are available in PHP 5.3 and not in PHP 5.2 or less. This creates a big issue, as most users don't have the latest version.
I want now, after getting the plugin 99% done, to do the following
Test my code with some kind of an app. where I can put the minimum PHP version. That App. or program would find out functions like json_encode. Not sure if that is possible, but would probably solve most of my problem.
Is it possible to get the native code of the PHP functions in PHP. I'm not sure if they are written in PHP or not, if so where can I get them. If not, what's the best option to find replacement for these functions. Certainly, I don't want to be re-coding them from scratch
What's the best methodology to implement the functions. I found some developers that check for the PHP version, while others check if the functions exist. Which one is best and why?
Would love also to read about your deployment strategies and how you dealt with that particular problem.
2.Nope. They're provided by compiled extensions written in C. For json_encode (which BTW is available since 5.2 not 5.3) you can use Zend_Json as an alternative
3.Checking if function exist is the best if you want to be 100% sure. After all, one can be running a self compiled version of PHP with not all core functions available. Check PHP version number, to know if features like namespaces, exception chaining etc are available.
You can use PEAR's
PHP_Compat to provide missing functionality for older versions of PHP and
PHP_CompatInfo to find out the minimum version and the extensions required for a piece of code to run
If you want to provide your own userland implementations of functions or classes, you are good advised to provide them wrapped into function_exists or class_existsblocks, so they dont interfere with PHP versions providing those methods.
I don't really know how Wordpress plugins work but except if you really want your to be able to run on old PHP version, you'll need to check for available function and provide an alternative, which can lead you code to be messy.
If you can, and want to educate your users, you can simply version_compare() function to compare version against a well tested and fully functionnal PHP version and throw a educationnal and explicative message to your end users.
if (version_compare(PHP_VERSION, '5.3.0') <= 0) {
echo 'You need to run PHP 5.3.0 to use this plugin';
}
Re 1.) there may be such an application, but there also may be not. What you usually want to do is to keep close tabs on each function you use in the manual, which states what PHP version(s) are needed.
Re 2.) if a function is PHP 5.3 or 5.2 only, you will usually find a replacement suggestion in the User Contributed Notes or on Stack Overflow. (Be careful what you use though, a lot of the code in the UCN is bad - but in that case, there is usually at least one comment saying so.)
Re. 3.) it probably doesn't matter, but checking for whether a function exists is surely the safest way.
I have a PHP class I want to convert to a PHP extension. I checked some tutorials (tuxradar's writing extensions, php.net's extending php, and zend's extension writing) and it's a bit complicated.
I found the article "How to write PHP extensions" (ed note: site is defunct) and I wanted to know if it is possible to use this to make it grab a PHP class from a certain path (say /home/website1/public_html/api/class.php), execute it and return the class instance.
This way it will be usable in other websites that are hosted on the same server – each can simply call the function and it will obtain its own instance.
Is that possible?
The question as I understand it now is, The user has a PHP class that they would like to share with multiple people, but does not want to share the source code.
There are many solutions to this, they generally invovle turning the PHP code into some kind of byte code, and using a PHP extension to run the byte code. I've never used any of these solutions, but I'm aware of the following:
phc is an open source compiler for PHP
Zend Guard
HipHop for PHP - I'm unsure about this, but Facebook recently released it so it might be worth a look.
I'm sure there are others. Just Google for PHP Compiler, or PHP Accelerator.
In one sentence: I don't believe so, I think its a lot more work than that.
No, there is not tool that can do that.
Anyway, what you want call be easily accomplished with auto_prepend_file. Just make that ini directive point to a PHP file that has the class definition, and then it will be available to all the applications.
If you don't want the users to be able to use the source, you can use one the several zend extensions that allow you to pre-compile the file and use it in that form.
You can extend underlying C library functions into PHP space by writing PHP extensions. However, i think in your case you don't need to write one.
I am aware that this is an old question (being from 2012) however the answer has changed and there is now a tool that can do this. Jim Thunderbirds PHP-to-C Extension toolset provides the means to take a simple class in one file all the way up to a complicated multi file multi-level namespaced framework and convert it to a C-extension that can then be installed into your PHP server.
While in many use cases doing so is not needed as the ordinary PHP code will work just as good in some cases significant performance improvements can be experienced. The information page shows that an ordinary class (deliberately designed to take a long time) took 16.802139997482 seconds as plain vanilla PHP, and 3.9628620147705 as a PHP extension built using the tool.
As an added advantage the tool also provides an additional feature. The ability to combine PHP code (to be converted to C) and native C code within the same extension which can produce even greater performance enhancements. The same example used above only tool 0.14397192001343 seconds when much of the intensive code was moved to a bubble sort C code and simply calling it from within the PHP code.
As a side note functionally to the end developers using the code using the extension is very much similar to having the files manually included in the PHP file being developed except it doesn't have to be specifically included as it is done through the PHP extensions component.
(Disclaimer: I am not affiliated with this developer but am glad to have come across it as it is thus far working for converting some of my intensive classes into PHP extensions without needing to know C).
I'm trying to accomplish a task and turns out that the code I need is packaged as a PHP extension, which according to what I've been told means I have to have root access to install it (I'm on shared hosting so that's a bit of a problem.
I'll solve this problem later, but for now I'm trying to understand the difference between an extension, a library, and a class. Is it more of a packaging thing that could be overridden and repackaged a different way, or is there a valid architectural reasoning behind it?
Also when releasing your own code, what makes you decide to release as library vs. class vs. extension? or do you go with whichever sounds better?
thanks in advance.
P.S. If you must know which extension I'm talking about, it's Libpuzzle, but that's really beside the point, my question is more general.
An extension is a pice of code programmed in C which will be included into the PHP core when PHP starts. Normally you have some more native functions available after including a extension. For example a zip functionality.
A class is a abstract pice of PHP code which solves common tasks. For example sending emails. You can find some common classes at pear.php.net.
A library is a collection of PHP classes wich solve more generic tasks for example buliding HTML forms AND sending emails. The Zend Framework is a framework which consists of many, many PHP classes.
Normally extension features can be programmed in PHP. For example the PEAR::Compat class. Often you will find the functionality you need as a PHP class available. I'm sure the stackoverflow readers will supply you with ideas where to find a specific PHP class.
Extensions are low-level. Usually written in C/C++, and compiled into native-code shared libraries, they interact with the Zend Engine directly. It has pros and cons, main advantages being the speed and more control; and main disadvantages - they are harder to install, and require compilation (and that requires a compiler and PHP headers); it's not true they require root access though - you only need ability to use custom php.ini (or dl() function, but I see they deprecated it for some reason).
Libraries/classes are high-level and interpreted. If you don't know if you need to write extension, then you probably don't. About what classes are - read about OOP. A library is a reusable collection of code (most commonly in form of functions/classes).
Some libraries (including libpuzzle) also include a command-line tool. So if you're unable to use the PHP library due to your shared hosting environment, maybe you can compile the command-line tool. Then you can run it from PHP using something like exec. It will be slower and require more memory than a library, but it might get the job done. Of course, many hosts also have restrictions on commands like exec, so this might not work either.
I'm writing an interposition library to track the usage of some library functions in libc, such as open(), close(), connect(), etc. It works generally well on most of the applications. However, when I try it with PHP, using PHP's MySQL module in particular, none of the function calls to libc inside this module is been tracked (so no connect(), no socket(), etc.). 'strace' told me that the system calls socket(), connect(), etc., took place. Running 'file' on the module and libmysqlclient.so.16.0.0 said that they are all dynamically linked. So it shouldn't be a problem caused by static linkage. What might be the problem?
I'm using Fedora 11 64-bit version.
Thank you.
It seems like that it was not caused by static linkage. In fact, PHP is dynamically linked to other libraries. The problem relies in the way PHP loads extensions.
PHP loads extensions by calling dlopen() with flags RTLD_LAZY, which means that the symbol will only be resolved when the reference is executed. This bypasses the interposition specified by LD_PRELOAD.
It's possible that the library may be invoking system calls directly for some reason. In this case you'd need to use strace (or ptrace() in your own program) to track this usage.
I agree with the answer above that these libraries may be bypassing the calls to open(), write(), etc in libc.. In other words, those libraries may be calling the system calls directly using assembly and not using the libc interface.. although it is not all that common to see applications using the syscalls directly, it is not unheard of..
If that's the case, that's why you would not see any interception in your library interposition experiment.. You have two ways then, the quick one through strace and the more complex one in building a kernel module that will intercept these calls at the kernel level and reporting to whatever framework you are building..
Have fun..
ErnestoB