Call PHP function with less parameters then expected by function - php

I have the following PHP function which is working very well:
<?php
function my_test_function($par1, $par2, $par3) {
$string = $par1.$par2.$par3;
return $string;
}
echo my_test_function('Hello', 'how are', 'you');
?>
But if I call the function like this:
echo my_test_function('Hello', 'how are');
I'll get an error message, because the function needs three parameters and I only send two parameters:
[29-Jan-2023 10:29:45 UTC] PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function my_test_function(), 2 passed in /home/user/public_html/test_file.php on line 7 and exactly 3 expected in /home/user/public_html/test_file.php:2
Stack trace:
#0 /home/user/public_html/test_file.php(7): my_test_function('Hello', 'how are')
#1 {main}
thrown in /home/user/public_html/test_file.php on line 2
Is there a way to send less parameters than expected by the function? I'd like to call the function with two parameters, although tree are expected.
I know, I could just make the third parameter empty but this isn't my goal.

You can make a parameter optional like this:
<?php
function my_test_function($par1, $par2, $par3 = "all of you") {
$string = $par1.$par2.$par3;
return $string;
}
echo my_test_function('Hello', 'how are', 'you');
echo my_test_function('Hello', 'how are');
?>
This will return:
Hellohow areyou
Hellohow areall of you

if you want to use a function without knowing the number of arguments there is a technique that will please you, it is to use spread operators.
here is the link of the php doc
you can do write function like that :
function concatMyXStrings(...$strings){
$out = '';
foreach($strings as $string){
$out .= $string;
}
return $out;
}
you pass 1 or x arguments, almost without worrying about what you will send or receive...
concatMyXStrings('I', ' ', 'love ', ' stack', ' ', ' !');
// or
concatMyXStrings('pink ', 'floyd');
you loop on it like an array to forge your string by concatenating at each iteration and normally, with that, you're saved!
edit : you can also use implode pour concatenation like this for avoid using a foreach loop
// ...
return implode('',$strings);
// ...

Related

"Warning: preg_replace_callback(): Requires argument 2, '&#x;', to be a valid callback" ; PHP Error

Setting up an App that should put Ads over images and I'm getting this WordPress error when running the code and it's been a frustrating week trying to fix this thing.
function cwali_json_encode_utf8callback($matches){
return html_entity_decode('&#x' . $matches[1] . ';', ENT_COMPAT, 'UTF-8');
}
function cwali_json_encode_utf8($json)
{
return preg_replace_callback('/\\\\u(\w{4})/', cwali_json_encode_utf8callback($matches), json_encode($json));
}
I expect it to work but it gives me the following error : Warning: preg_replace_callback(): Requires argument 2, '&#x;', to be a valid callback.
If someone could please come up with a solution, that would be amazing, thank you so much!
In your call
preg_replace_callback('/\\\\u(\w{4})/', cwali_json_encode_utf8callback($matches), json_encode($json));
instead of passing the callback function, you call the function, so its return value is passed as the argument. Try
preg_replace_callback('/\\\\u(\w{4})/', 'cwali_json_encode_utf8callback', json_encode($json));

Catchable fatal error: Argument 1 passed to CorenlpAdapter::getOutput()

I get the following error:
Catchable fatal error: Argument 1 passed to CorenlpAdapter::getOutput() must be an instance of string, string given, called in /Library/WebServer/Documents/website/php-stanford-corenlp-adapter/index.php on line 22 and defined in /Library/WebServer/Documents/website/php-stanford-corenlp-adapter/src/CoreNLP/CorenlpAdapter.php on line 95
index.php 21 and 22 contain:
$text1 = 'I will meet Mary in New York at 10pm';
$coreNLP->getOutput($text1);
corenlpAdapter.php lines 95 and onwards contain:
public function getOutput(string $text){
if(ONLINE_API){
// run the text through the public API
$this->getServerOutputOnline($text);
} else{
// run the text through Java CoreNLP
$this->getServerOutput($text);
}
// cache result
$this->serverMemory[] = $this->serverOutput;
if(empty($this->serverOutput)){
echo '** ERROR: No output from the CoreNLP Server **<br />
- Check if the CoreNLP server is running. Start the CoreNLP server if necessary<br />
- Check if the port you are using (probably port 9000) is not blocked by another program<br />';
die;
}
/**
* create trees
*/
$sentences = $this->serverOutput['sentences'];
foreach($this->serverOutput['sentences'] as $sentence){
$tree = $this->getTreeWithTokens($sentence); // gets one tree
$this->trees[] = $tree; // collect all trees
}
/**
* add OpenIE data
*/
$this->addOpenIE();
// to get the trees just call $coreNLP->trees in the main program
return;
}
Why exactly am I getting this error when text1 is a string?
I am the original author of this class. As you can see, the function getOutput looks like this:
public function getOutput(string $text){
...
}
Change that to:
public function getOutput($text){
...
}
The function tries to enforce that the input is string. The original code should work. However, it seems that in your case, PHP thinks "string" is not actually a string. Maybe the coding environment (the IDE) you are using uses the wrong character set? Or maybe you copy-pasted the code from HTML into the IDE or something like that. Thus whilst it says "string" on the screen, it's not actually a string to PHP.
If you are sure the input is a string, you can safely change the code like above. The class should then work normally.
public function getOutput($text){
.
.
.
}

preg_replace_callback(): Requires argument 2 to be a valid callback in

$ent_check = empty($modSettings['disableEntityCheck']) ?
array('preg_replace_callback(\'~(&#(\d{1,7}|x[0-9a-fA-F]{1,6});)~e\', \'$func[\\\'entity_fix\\\'](\\\'\\2\\\')\', ', ')') :
array('', '');
Warning: preg_replace_callback(): Requires argument 2, '$func['entity_fix']('\2')', to be a valid callback in...
I'm not quite sure what to do here. Any help from someone smarter than I would be greatly appreciated...
The First issue here is Intent. Well, the 2nd Argument passed to preg_replace_callback($arg1, $arg2...) is expected to be a Callable. That is why you have that error. It is unclear where you are going with your code but perhaps the code below could throw more light and help you either rethink/clarify your question, intent + goal or revisit your code. Consider this:
<?php
$string = "&#2510 whatever &#5870 again whatever &#7885";
$modSettings = array('disableEntityCheck'=>array());
$func = array(
"fix_stuff" => function($param=20){ echo $param;},
"do_stuff" => function($param=10){ echo $param;},
"entity_fix" => function($matches ){ return $matches[0] . "YES!!! ";},
);
$ent_check = empty($modSettings['disableEntityCheck']) ? array(preg_replace_callback('#\d#', $func['entity_fix'], $string )) : array('', '');
var_dump($ent_check);
// DISPLAYS
array (size=1)
0 => string '&#2YES!!! 5YES!!! 1YES!!! 0YES!!! whatever &#5YES!!! 8YES!!! 7YES!!! 0YES!!! again whatever &#7YES!!! 8YES!!! 8YES!!! 5YES!!! '
Notice that in the code above, the 2nd Argument passed to preg_replace_callback is a function though passed as a REFERENCE to the 'entity_fix' Key of the array: $func. This was intended to highlight the fact that it is also possible to pass the 2nd Argument in such a manner. It is hoped that this here gives you a little tip to kick off ;-)
Good Luck!!!

How to translate strings in PHP in dependancy of gender and count?

I am working on multilingual application with a centralized language system. It's based on language files for each language and a simple helper function:
en.php
$lang['access_denied'] = "Access denied.";
$lang['action-required'] = "You need to choose an action.";
...
return $lang;
language_helper.php
...
function __($line) {
return $lang[$line];
}
Up til now, all strings were system messages addressed to the current user, hence I always could do it that way. Now, I need create other messages, where the string should depend on a dynamic value. E.g. in a template file I want to echo the number of action points. If the user only has 1 point, it should echo "You have 1 point."; but for zero or more than 1 point it should be "You have 12 points."
For substitution purposes (both strings and numbers) I created a new function
function __s($line, $subs = array()) {
$text = $lang[$line];
while (count($subs) > 0) {
$text = preg_replace('/%s/', array_shift($subs), $text, 1);
}
return $text;
}
Call to function looks like __s('current_points', array($points)).
$lang['current_points'] in this case would be "You have %s point(s).", which works well.
Taking it a step further, I want to get rid of the "(s)" part. So I created yet another function
function __c($line, $subs = array()) {
$text = $lang[$line];
$text = (isset($sub[0] && $sub[0] == 1) ? $text[0] : $text[1];
while (count($subs) > 0) {
$text = preg_replace('/%d/', array_shift($subs), $text, 1);
}
return $text;
}
Call to function looks still like __s('current_points', array($points)).
$lang['current_points'] is now array("You have %d point.","You have %d points.").
How would I now combine these two functions. E.g. if I want to print the username along with the points (like in a ranking). The function call would be something like __x('current_points', array($username,$points)) with $lang['current_points'] being array("$s has %d point.","%s has %d points.").
I tried to employ preg_replace_callback() but I am having trouble passing the substitute values to that callback function.
$text = preg_replace_callback('/%([sd])/',
create_function(
'$type',
'switch($type) {
case "s": return array_shift($subs); break;
case "d": return array_shift($subs); break;
}'),
$text);
Apparently, $subs is not defined as I am getting "out of memory" errors as if the function is not leaving the while loop.
Could anyone point me in the right direction? There's probably a complete different (and better) way to approach this problem. Also, I still want to expand it like this:
$lang['invite_party'] = "%u invited you to $g party."; should become Adam invited you to his party." for males and "Betty invited you to her party." for females. The passed $subs value for both $u and $g would be an user object.
As mentionned by comments, I guess gettext() is an alternative
However if you need an alternative approach, here is a workaround
class ll
{
private $lang = array(),
$langFuncs = array(),
$langFlags = array();
function __construct()
{
$this->lang['access'] = 'Access denied';
$this->lang['points'] = 'You have %s point{{s|}}';
$this->lang['party'] = 'A %s invited you to {{his|her}} parteh !';
$this->lang['toto'] = 'This glass seems %s, {{no one drank in already|someone came here !}}';
$this->langFuncs['count'] = function($in) { return ($in>1)?true:false; };
$this->langFuncs['gender'] = function($in) { return (strtolower($in)=='male')?true:false; };
$this->langFuncs['emptfull'] = function($in) { return ($in=='empty')?true:false; };
$this->langFlags['points'] = 'count';
$this->langFlags['toto'] = 'emptfull';
$this->langFlags['party'] = 'gender';
}
public function __($type,$param=null)
{
if (isset($this->langFlags[$type])) {
$f = $this->lang[$type];
preg_match("/{{(.*?)}}/",$f,$m);
list ($ifTrue,$ifFalse) = explode("|",$m[1]);
if($this->langFuncs[$this->langFlags[$type]]($param)) {
return $this->__s(preg_replace("/{{(.*?)}}/",$ifTrue,$this->lang[$type]),$param);
} else {
return $this->__s(preg_replace("/{{(.*?)}}/",$ifFalse,$this->lang[$type]),$param);
}
} else {
return $this->__s($this->lang[$type],$param);
}
}
private function __s($s,$i=null)
{
return str_replace("%s",$i,$s);
}
}
$ll = new ll();
echo "Call : access - NULL\n";
echo $ll->__('access'),"\n\n";
echo "Call : points - 1\n";
echo $ll->__('points',1),"\n\n";
echo "Call : points - 175\n";
echo $ll->__('points',175),"\n\n";
echo "Call : party - Male\n";
echo $ll->__('party','Male'),"\n\n";
echo "Call : party - Female\n";
echo $ll->__('party','Female'),"\n\n";
echo "Call : toto - empty\n";
echo $ll->__('toto','empty'),"\n\n";
echo "Call : toto - full\n";
echo $ll->__('toto','full');
This outputs
Call : access - NULL
Access denied
Call : points - 1
You have 1 point
Call : points - 175
You have 175 points
Call : party - Male
A Male invited you to his parteh !
Call : party - Female
A Female invited you to her parteh !
Call : toto - empty
This glass seems empty, no one drank in already
Call : toto - full
This glass seems full, someone came here !
This may give you an idea on how you could centralize your language possibilities, creating your own functions to resolve one or another text.
Hope this helps you.
If done stuff like this a while ago, but avoided all the pitfalls you are in by separating concerns.
On the lower level, I had a formatter injected in my template that took care of everything language-specific. Formatting numbers for example, or dates. It had a function "plural" with three parameters: $value, $singular, $plural, and based on the value returned one of the latter two. It did not echo the value itself, because that was left for the number formatting.
The whole translation was done inside the template engine. It was Dwoo, which can do template inheritance, so I set up a master template with all HTML structure inside, and plenty of placeholders. Each language was inheriting this HTML master and replaced all placeholders with the right language output. But because we are still in template engine land, it was possible to "translate" the usage of the formatter functions. Dwoo would compile the template inheritance on the first call, including all subsequent calls to the formatter, including all translated parameters.
The gender problem would be getting basically the same soluting: gender($sex, $male, $female), with $sex being the gender of the subject, and the other params being male or female wording.
Perhaps a better aproach is the one used by function t in Drupal, take a look:
http://api.drupal.org/api/drupal/includes!bootstrap.inc/function/t/7
http://api.drupal.org/api/drupal/includes!bootstrap.inc/function/format_string/7

Can I make a PHP "macro" (like #define) to supply parameters for function calls?

The parameters that I am talking about are __FILE__ and __LINE__ - those of the caller of the function, so that the function can use them in error reporting.
Let's say that I have two files and line 100 of file_1.php calls my_func() in file_2.php
I'd like to make that call my_func(__FILE__, __LINE__) so that if my_func encounters an error it can report it against file_1.php at line 100.
I do that since there are hundreds of calls to my_func and reporting the error to be in my_func() itself might not be informative (unless I dump the stack). And I don't want to have to manually type those two parameters a few hundred times.
In C I would do something like #define MY_FUNC my_func(__FILE, __LINE) - can I do something similar in PHP?
Unfortunately, PHP does not have any kind of macros. You could implement these yourself by running a command line tool like sed over some input to insert macros, but that is error prone and a bit sloppy.
To do what you want to do, you might consider the debug_backtrace function.
You can replicate C-like macros with the help of source file re-writing.
Write file macro.php:
<?php
$name = $_SERVER['PHP_SELF'];
$name = preg_replace('#\/#mui', '', $name);
$file = file_get_contents($name);
// get defined macros
preg_match_all('#\#macro\h+(\w+)\h+(.*)$#mui', $file, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
// delete macro definition
$file = str_replace($m[0], '', $file);
// substitute macro => value
$file = str_replace($m[1], $m[2], $file);
}
// save processed file
$new_name = '/var/tmp/' . $name . '.pr';
file_put_contents($new_name, $file);
include_once $new_name;
exit;
Now with such tool, usage is simple:
<?php
include_once "macro.php";
#macro DEBUG_INFO ;echo('<b> DEBUG_INFO: __FILE__ : ' . __FILE__ . ';__LINE__ : ' . __LINE__ . '</b>')
echo '<br>'.(1/2); DEBUG_INFO;
echo '<br>'.(1/0); DEBUG_INFO;
echo '<br>'.(0/0); DEBUG_INFO;
When executed outputs:
0.5 DEBUG_INFO: FILE : /var/tmp/test.php.pr;LINE : 7
INF DEBUG_INFO: FILE : /var/tmp/test.php.pr;LINE : 8
NAN DEBUG_INFO: FILE : /var/tmp/test.php.pr;LINE : 9
I have strong C background and always missed C-like macros in PHP. But hopefully we can inject some sort of replacement for it.
Nope. Use a stack trace: debug_backtrace(). You can retrieve the file and line of the caller, by simply looking at the second row in the returned array.
Unfortunately there is no C like Macros in PHP.
reading a debug_backtrace is tricky and I don't like that.
What I would like to throw an exception at error points then exception object it self contains the stack trace as well as the line number and file it's coming from.
catch (Exception $e)
{
$errorMessage = $e->getMessage() . " LINE: " .$e->getLine(). " FILE: " . $e->getFile();
}

Categories