PHP is my function called from echo, or sprintf - php

I want to look where the function is called.
Is the function called inside a echo or sprintf? Then return, otherwise echo the content.
I got this code (test.php):
<?php
function __($str = '')
{
// who is my parent?
$parent=debug_backtrace();
if ( isset ( $parent[1] ) )
$parent = $parent[1]['function']; //Did it!
else
$parent = debug_backtrace()[1]['function']; //Try
if ( empty ( $parent ) )
$parent = "ERROR!";
return sprintf("[%s] %s.%s", $parent, $str, PHP_EOL);
}
__('does nothing');
echo __('test from echo #1');
echo(__('test from echo #2'));
echo sprintf(__('test from sprintf #1'));
echo(sprintf(__('test from sprintf #2')));
?>
When I type it at the terminal all I get is:
WDGMBP:Test Wes$ php test.php
[ERROR!] test from echo #1.
[ERROR!] test from echo #2.
[ERROR!] test from sprintf #1.
[ERROR!] test from sprintf #2.
(p.s. from web the same)
My PHP version is:
WDGMBP:BIHappyV3 Wes$ php -v
PHP 5.5.27 (cli) (built: Aug 22 2015 18:20:44)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies

You're confused about how debug_backtrace works. It returns the functions that were executing to make the call, not the function that will be called with the result. E.g. if you have:
function testit() {
someFunc(__('something'));
}
then $parent[1]['function'] will contain testit, not someFunc.
I don't think there's any way to get someFunc. That function isn't anywhere on the stack, because it doesn't get called until after __() returns.

Related

PhpStorm override function

Return type of explode function has changed in PHP 8.0.
With PhpStorm 2022.1.3 + Php Inspections (EA Extended) 4.0.7.1 inspect code (PHP 7.2 level), I get many:
[EA] '$xyz' may not support offset operations (or its type not annotated properly: [bool, array]).
In PhpStorm configuration, is there a way to override default explode function?
I tried to add .phpstorm.meta.php/explode.php, but this is not working. I think it's wrong.
<?php
namespace PHPSTORM_META {
override( explode,
function explode(string $separator, string $string, int $limit): array {
return [];
}
);
}
I ask that because, I get the previous "error" with the following code with PHP 7.2-7.4, and not with PHP 8.0 (for $gps[0] and $gps[1]):
$gps = explode(',', $result['GPS']);
if (count($gps) == 2) {
$items['lat'] = $gps[0];
$items['lng'] = $gps[1];
}

DOMDocument->save() fails after user_abort is handled

In PHP, its possible to register shutdown functions, which (sometimes gets ignored, however) is definetely called in my scenario, see below.
PHP/libxml supported by the DOMDocument class in PHP does not play along well w/ my registered shutdown functions, if I want to call ->save() (->saveXML() works fine) after user abort (e.g. from registered shutdown function or a class instance destructor). Related is also the PHP connection handling.
Let the examples speak:
PHP version:
php --version
PHP 7.1.4 (cli) (built: Apr 25 2017 09:48:36) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
To reproduce user_abort I'm running the php through python2.7 run.py:
import subprocess
cmd = ["/usr/bin/php", "./user_aborted.php"]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
# As this process exists here and the user_aborted.php
# has sleeps/blocks in for-cycle thus simulating a user-abort
# for the php subprocess.
The php script user_aborted.php to try saving XML in shutdown function :
<?php
ignore_user_abort(false);
libxml_use_internal_errors(true);
$xml = new DOMDocument();
$xml_track = $xml->createElement( "Track", "Highway Blues" );
$xml->appendChild($xml_track);
function shutdown() {
global $xml;
$out_as_str = $xml->saveXML();
fwrite(STDERR, "\nout_as_str: " . var_export($out_as_str, true) . "\n");
$out_as_file = $xml->save('out.xml');
fwrite(STDERR, "\nout_as_file: >" . var_export($out_as_file, true) . "<\n");
fwrite(STDERR, "\nerrors: \n" . var_export(libxml_get_errors(), true) . "\n");
}
register_shutdown_function('shutdown');
$i = 2;
while ($i > 0) {
fwrite(STDERR, "\n PID: " . getmypid() . " aborted: " . connection_aborted());
echo("\nmaking some output on stdout"); // so user_abort will be checked
sleep(1);
$i--;
}
Now, if I run this script w/o user abort (simply calling PHP) with:
php user_aborted.php the XML gets saved properly.
However when calling this through python2.7 (which simulates the user abort by exiting the parent process), python2.7 run.py the weirdest things happen:
the out_as_str value is fine, looks the XML I wanted
BUT the file out.xml is an empty file
ALSO the libxml_get_errors reports FLUSH problems
The output w/ python looks:
python2.7 run.py
PID: 16863 aborted: 0
out_as_str: '<?xml version="1.0"?>
<Track>Highway Blues</Track>
'
out_as_file: >false<
errors:
array (
0 =>
LibXMLError::__set_state(array(
'level' => 2,
'code' => 1545,
'column' => 0,
'message' => 'flush error',
'file' => '',
'line' => 0,
))
)
Sorry for the long post, but I was looking through PHP/libxml2 code the whole day w/o any success. :/
Reason:
It turns out this is due to a fix for a previous bug.
Links:
previous PHP bug ticket which fix introduced the deffect
commit that introduces the deffect (GitHub)
The linked php_libxml_streams_IO_write function is the writecallback (set in ext/libxml/libxml.c) for the buffer of the docp object, which is handed over for the libxml call on ext/dom/document.c. Ending up in libxml xmlIO.c where the buffer is NULL hence the file given over for ->save(*) does not get written.
Workaround:
Use the ->saveXML() to get the XML representation in string and write it using file_put_contents(*) by "hand":
$xml_as_str = $xml->saveXML();
file_put_contents('/tmp/my.xml', $xml_as_str);

How to pass variables to PHP to Python function?

I have the code in PHP side:
function apiTest($arga){
if (!isset($arga['name'])) {
printf("Missing required parameter 'name'\n");
return RET_PARAMSMISSING;
}
$retVal = 'testing';
printf("JSON:\n%s",json_wrapper($retVal)
return RET_NOERROR;
}
case 'testing':
$retval = apiTest($arga);
break;
In Browser running this script locahost/testing.php. Here is printing correctly:
TIDBITS API
C:/wamp/www/testing.php running # Sat, 10 Dec 2016 14:08:06
Executing function 'Test'
JSON:
testing
RETURN: 0
Here is json_wrapper printing the output correctly.
This Json_wrapper value how to pass to python function.
I have tried using the below code, but it's not working.
def inventory(self, **kwargs):
return self.tidbitsapi('testing')
I need to get the PHP variable to python side and perform some operation and once pass to return value true/false to PHP.
Try using a system call:
from php:
system('C:/pythonXX/python.exe pathToPythonModule.py "' . arg . '"')
from python:
import sys
if __name__ == '__main__':
if len(sys.argv) > 2:
varFromPhp = sys.argv[2]
print(varFromPhp)
else: print("Didn't get parameter")

php extension in-out parameter

I'm writing a php extension using c++. The c++ function signature is:
bool validateAndNormalizeStr (string& str)
Here 'str' is a in-out parameter. It's value would be updated in the function.
I hope the php function has the same signature. Here is a use case:
$str = " zh-hans-cn";
$ret = validateAndNormalizeStr($str);
if($ret)
{
echo $str;
}
I hope the output is: "zh-Hans-CN".
The problem is I haven't found any document about in-out parameter handling in writing php extension. Help!!!
Thanks

PHP inclusion behaving oddly with multiple includes

I have the following code:
if (include_once(dirname(__FILE__).'/file.php')
|| include_once(dirname(__FILE__).'/local/file.php')
)
{
This causes an error because PHP tries to include "1" (presumably dirname(__FILE__).'/file.php' || dirname(__FILE__).'/local/file.php')
Commenting out the second line makes this work as intended, other than the fact it won't use the second file. Do I really need to use elseif and code duplication here, or is there a way to get this working?
$ php --version
PHP 5.2.6-3ubuntu4.2 with Suhosin-Patch 0.9.6.2 (cli) (built: Aug 21 2009 19:14:44)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
Group the include statements:
if ( (include_once dirname(__FILE__).'/file.php')
||
(include_once dirname(__FILE__).'/local/file.php')
)
See example #4 in the manual page:
<?php
// won't work, evaluated as include(('vars.php') == 'OK'), i.e. include('')
if (include('vars.php') == 'OK') {
echo 'OK';
}
// works
if ((include 'vars.php') == 'OK') {
echo 'OK';
}
?>
Try using parentheses to subdue the operator precedence.
if ( (include_once('xml.php')) || (include_once('xml.php')) ) {
echo 'bah';
}

Categories