Overview
In PHP 5.6 it seems that adding declare(ticks=1) and then using register_tick_function() would follow any includes and provide profiling information accordingly.
In PHP 7+ however it now seems I have to add declare(ticks=1) in every file. I use this for profiling every method call on a page load and don't now want to add this to each PHP file in my system (some I can't if they are in libraries).
I can't find anything in the docs about changes that were made to this.
Replication Steps
Create the below 2 files:
index.php
<?php
declare(ticks=1);
$count = 0;
register_tick_function('ticker');
function ticker() {
global $count;
$count++;
}
$foo = 'foo';
$bar = 'bar';
include dirname(__FILE__) . '/inc.php';
echo $count;
inc.php
<?php
#declare(ticks=1);
$baz = "baz";
$qux = "qux";
Results
Running php index.php in the terminal gives me:
PHP 5.6 - 7
PHP 7.0 - 5
With declare(ticks=1) uncommented in inc.php the results are:
PHP 5.6 - 8
PHP 7.0 - 8
Question
Is there any way to way to force it to follow includes and in a sense make it global in PHP 7+?
According to the PHP bug filed at https://bugs.php.net/bug.php?id=71448
Due to an implementation bug, the declare(ticks=1) directive leaked into different compilation units prior to PHP 7.0. This is not how declare() directives, which are per-file or per-scope, are supposed to work.
So in fact it was a bug that it ever did work as it did in PHP 5.6 and the correct implementation has been added in PHP 7.0. Unfortunately this means it will never work but at least there is an explanation.
There is an answer on the below question that shows how to achieve this in PHP 7+
Natively profile multiple scripts in PHP7
Related
I have written a PHP library using the PHP 8.0 readonly keyword and then I realised that it would be good to support earlier versions of PHP such as 7.4.
I could easily remove the readonly keywords from my code but I don't want to do that -- they were put there for a reason!
Having a C background, I immediately thought of macros but PHP doesn't seem to have any. I've googled this answer for adding macro-like behaviour to PHP, but it looks like an overkill. And it's just for one file, and my library has 26 files at present.
Is there an easy way to make PHP 7.4 just ignore the readonly keyword and make my code cross-version? Something to the effect of this C code?
#if PHP_VERSION < 8
#define readonly /**/
#enif
Perphaps some composer build option that can pre-process files before packaging them up?
Out of the box, PHP does not include conditional compilation of the type you're hoping for.
One option would be to pre-process the source files on the fly, using a custom autoloader or Composer hook. The idea would be to let the normal code run to the point where it was going to include the file, then instead fetch its contents and manipulate it.
Note that this would not need to be a fully-functional macro system, you could just surround the code with some clear markers, like /* IF PHP 8 */ readonly /* END IF */ and match them with a simple regex pattern:
$php_code = file_get_contents($php_file_being_loaded);
if ( PHP_VERSION_ID < 80000 ) {
$php_code = preg_replace('#/\* IF PHP 8 \*/.*?/\* END IF \*/#s', '', $php_code);
}
eval($php_code);
Alternatively, you could run the pre-processing "offline", to automatically produce parallel versions of the library: one for PHP 8.0 and above, and a different one for PHP 7.4. Again, this could be as simple as the above, or you could use a tool like Rector which parses and rewrites normal PHP code (with no extra markers) according to set rules, including "downgrading" it to be compatible with a particular version of PHP.
PHP is not being compiled, therefore there's no compiler macros.
According to Backward Incompatible Changes it's a new keyword:
readonly is a keyword now. However, it still may be used as function name.
So you have two choices: a) don't re-assign it's value or b) maintain two versions.
most frameworks simply avoid using modern features for this reason alone (WordPress, Symfony, Laravel), but if you insist, your best bet is probably Composer, you can have a v1.x.x with composer.json
{
"require": {
"php": ">=7.4"
},
}
and a v2.x.x with composer.json
{
"require": {
"php": ">=8.0"
},
}
then when people do composer require lib, composer will automatically scan for and install the newest version of your library that is compatible with the local php version and composer.json-constraints (-:
the downside is that you'll have to maintain both v1 and v2 of your library for as long as you intend to support php 7.4 though..
another option is to have a loader like lib.php
if(PHP_MAJOR_VERSION >= 8){
require("lib_modern.php");
} else{
require("lib_legacy.php");
}
again with the downside of having to maintain both lib_modern and lib_legacy
How do I use PHP 8.0 to determine the Apache installation path in a Windows environment?
No: I know where it is manually, I need to do this programmatically.
There was nothing in $_SERVER and I had to resort to digging through phpinfo(). The following allows you to reuse phpinfo() as $pinfo if you need to find other bits of information. Additionally PHP does not support the JavaScript index style (e.g. explode()[index]) on I think 7.2 and older so anyone stuck on those older versions may have to re-code the two explode in to separate lines.
//If you need additional items you can refer ONCE to $pinfo:
ob_start();
phpinfo();
$pinfo = ob_get_contents();
ob_end_clean();
if (PHP_OS == 'WINNT')
{
//explode()[index] will not work on PHP ~7.2 and older
echo explode('<', explode('>Server Root </td><td class="v">', $pinfo, 2)[1], 2)[0];
}
I am using php version 7 and defined a class that extend Thread class but when I run My Program that give me Class 'Thread' not found error.I searched and I found out I must copy pthreadVC2.dll in apache and system32 folders and copy php_pthreads.dll in php/ext and system32 folders and add extension=php_pthreads.dll to php.ini .I did all these works but I get that error again.php_pthreads.dll and pthreadVC2.dll version is 14
<?php
class exampleThread extends Thread
{
var $Mobile;
var $code;
public function __construct($Mobile, $code)
{
$this->Mobile = $Mobile;
$this->code = $code;
}
public function run()
{
}
};
?>
The pthreads extension cannot be used in a web server environment. It is only available in the CLI.
Whatever you're trying to do, you'll need to come up with another way of doing it.
As stated in the answer from duskwuff, the pthreads extension cannot be used in a web server environment.
We were playing around for about 1 week and unfortunately had to realize that running it in the CLI version leads to too many issues once it becomes too complicated --> we stopped and removed pthreads from our environment.
What I can suggest you:
Due to the fact we still need a multi-threaded functionality we were checking several methods and ended up using curl multi functions.
With curl multi functions you achieve a full multi-threading execution - and especially in our case - when you got lot of cores [we have 48] you can indeed use all of them when you spawn your tasks with curl...
The PHP curl multi exec documentation is very poor. I refer to this thread where you get additional information.
I am using wampserver to test & run wordpress code in my local computer. In order to run pthread, I have followed the following steps:
1) I got the pthread zip file from http://windows.php.net/downloads/pecl/releases/pthreads/0.44/
(My machine has php 5.3.13 and downloaded the php_pthreads-0.44-5.3-ts-vc9-x86.zip file from the above link).
2) Extracted the zip file. Moved the php_pthreads.dll to the C:\wamp\bin\php\php5.3.13\ext directory.
3) Moved pthreadVC2.dll to the C:\wamp\bin\php\php5.3.13 directory.
4) Then Opened C:\wamp\bin\php\php5.3.13\php.ini and added the code extension=php_pthreads.dll at the begining of the file.
But when I try to run the following code:
<?php
class My extends Thread {
public function run() {
printf("%s is Thread #%lu\n", __CLASS__, $this->getThreadId());
}
}
$my = new My();
$my->start();
?>
It gives me the following error:
Fatal error: Class 'Thread' not found in C:\wamp\www\wp-admin\includes\post.php on line 2
Can you please tell me how to install pthreads in my computer to use with php? and do I have to install any other software?
I've noticed that wampserver has php.ini in two separate places. One place is in the /wamp/bin/php/php5... directory, and the other place is in the /wamp/bin/apache/apache.../bin directory (where "..." represents version numbers). The two files need to be identical, because apparently both are loaded at different times by the overall wampserver boot-up procedure.
(Note I only discovered this recently, and may be well "behind the curve" of doing fancy things with wampserver --maybe everyone else has been dealing with both files for a long time. So I don't know if this simple thing will fix your problem; I came here looking for info, myself, regarding doing some multi-threading stuff. :)
One other thing. According to this page: www.php.net/manual/en/pthreads.requirements.php
PHP has to be compiled with "--enable-zts" in order for pthreads stuff to work. I have not been able to find any evidence that the PHP part of wampserver was compiled that way.
(months later)
Having decided I didn't really immediately need to do any threading stuff, I went on to do other things, until the need actually arose. I now can say that the version of PHP compiled into WampServer does support the "pthread" extension, although some set-up work is needed, first. The instructions I saw mentioned putting a couple of .dll files (after a download and unZip) into certain places, but that didn't work for me. Copying them to the \Windows\System32 directory did work. (Putting them into the \apache...\bin directory also works; there are some other php .dll files in there.)
After that, much like what you did, it is necessary to define a "class" that extends the "Thread" class, in order to actually do something in another thread. The "run()" function in the Thread class is "abstract", and needs to be "realized" as an actual function in the extended class. Then the "new" operator can create an "instance", an object of that specified class, for actual use. Here's the class that I needed:
//Purpose: Use another thread to run the code in another php file, after a delay
class xT extends Thread
{ var $fil, $tim;
function savWhatWhen($f="", $t=0)
{ $this->fil = $f; //save What, file to process
$this->tim = $t; //save When, delay before processing file
return;
}
function run()
{ ini_set('max_execution_time', 600); //600 seconds = 10 minutes
sleep($this->tim); //do a delay; beware of max-exec-time!
include($this->fil); //load file-to-process, and process it
return;
} }
That "savWhatWhen()" function was created specifically for this extension of the basic Thread class. Here's some code for using that class:
$TH = new xT(); //prepare a separate Thread
$TH->savWhatWhen("d:/wamp/myscripts/test.php", 45);//file-name and delay time
$TH->start(); //after delay, process file
//the code that does this can terminate, while OTHER thread is doing a delay
Note for anyone copying this code, you might need to make sure your "open_basedir" setting in the php.ini allows access to the specified file.
More months later: With lots of things being worked on, I haven't put a lot of time into using my pthread object. I did encounter a peculiarity that makes me wonder about whether or not I can actually use pthreads the way I had hoped. Here is what I have observed:
1. An initial php file is called by AJAX, to do something.
2. The PHP processor on the Web Server does that thing.
3. Various data is supposed to be echoed to the browser.
4. The initial php file calls for the creation of another thread, and terminates.
5. The browser does not yet receive the echoed data!
6. The PHP processor on the Web Server does the work delegated to the second thread.
7. When the second thread terminates, NOW the browser receives the echoed data!
At this writing I'm thinking I missed something. Perhaps I need to do some forceful "flush" stuff when the first thread ends, so that the browser can receive the echoed data and the user can do things while the PHP processor on the server is also doing things.
Check for extension_dir = "ext" in you php.ini file. Make sure it points to the folder where your extensions reside and make sure it's not commented (it has a semicolon ; in front of it)
You have to add a require_once() with the path of the Thread class before extending it (if your framework don't use an autoload class system)
I've encountered the same problem, in my case placing the pthreadVC2.dll in
..wamp\bin\apache\Apache2.4.4\bin
(instead of ..\wamp\bin\php\php5.4.16 as the guide in php.net instructs) solved the problem
Wamp server has a separate php.ini config file for the browser and for the cli.
To use the pthreads module in the browser with WAMP Server you need to copy the "pthreadVC2.dll" into the apache "bin" directory also.
You should now have he "pthreadVC2.dll" in both of these folders (if installed in default location):
C:\wamp\bin\php\php[x.x.xx]\bin
C:\wamp\bin\apache\apache[x.x.x]\bin
You will also need to update the php.ini file within the php bin directory AND the apache bin directory to include:
extension=php_pthreads.dll
This now means you can use pthreads in the browser and in the cli with wamp server
After encountering the same problem, I noticed that I have installed the wrong Pthread version (3.1.6 : requires PHP7+) which wasn't compatible with my PHP version (5.5.12). Solved the problem with Pthread version 0.0.44. An earlier version should probably work well.
Here is the download page for Pthread and the installation page. Be careful about the both php.ini location as mentioned above (Apache folder=for Browser, PHP folder=CLI).
When I check phpinfo(), I see /usr/local/php4/lib/php.ini
That means PHP4, right?
But When I execute the line of code below, it returns PHP5. WTF? I thought PHP4 did not have the DOMDocument class. I need to test for PHP4 and do a workaround, but this specific test is confusing me. Is there another more foolproof way to check for PHP4 in script?
if (is_admin() && class_exists('DOMDocument')) {
echo "PHP5";
} else {
echo "Awe PHP4";
}
The version of your PHP is listed right on top of any phpinfo() output. You can also determine it by echoing phpversion() or from CLI with php -v.
Apart from that, no. PHP4 does not support DOMDocument (at least not the one you are refering to). The old DOM XML extension has a similar named class though.
Try the following:
echo extension_loaded('domxml') ? 'old' : 'new';
phpinfo() is a cool function :)
edit, lots of similar functions here
http://www.php.net/manual/en/ref.info.php
you seem like you'd be interested in
phpversion() and version_compare()
The correct way to check your PHP version from phpinfo() is to read the header at the very top, but when doing checks in PHP code, checking php_version() is the way to do. There is also a predefined constant PHP_VERSION.
Well if phpinfo says you run php5 you are running php5. assuming by php_info you mean phpinfo.
you may wanna check the function phpversion
The path you are referring to is just the configured config file which could be anything.
You probably updated and kept it ages ago.