How to enable pathautocompletion from windows commandline - php

I want to ask the user to locate a folder on the (windows) commandline.
Usually you'll be able to use autocomplete with the [tab] key.
But not if I ask this from a phpscript.
I use this class:
<?php
class CLQuestion
{
protected $_awnser;
protected $_options;
protected $_question;
public function __construct($question, $options = array())
{
$this->_question = $question;
$this->_options = $options;
$this->askQuestion();
$this->waitForAwnser();
}
protected function askQuestion()
{
echo PHP_EOL . $this->_question . PHP_EOL;
}
protected function waitForAwnser()
{
while (true) {
$response = strtolower(trim(fgets(STDIN)));
// are options given?
if (empty($this->_options)) {
// no options given, so the response is our awnser
$this->_awnser = $response;
break;
} else if (!empty($this->_options) && in_array($response, $this->_options)) {
// options given and found in options
$this->_awnser = $response;
break;
} else {
// options given and not found.
echo PHP_EOL . 'Please use one of these options: ';
echo PHP_EOL . " " . implode(PHP_EOL . " ", $this->_options);
echo PHP_EOL;
continue;
}
}
}
public function getAwnser()
{
return $this->_awnser;
}
}
With this usage:
<?php
$question = new CLQuestion('Where is you folder located?');
$question->getAwnser(); // path typed
Windows CMD will give me a way to interact, but when i use the [tab] key, it does not autocomplete but it show a tab.
Am I able to activate path autocompletion in some way?

autocompletion is a feature of a windows shell prompt.
When you run an application like:
php script.php
this application gains control over STDIN and STDOUT and magic shell features like autocompletion will work no more until this app finishes.
This for example allows you to run one shell inside another.
If you need autocompletion in your script, you will need to implement it yourself. Instead of reading whole line with fgets(STDIN) you could read it char by char with fgetc(STDIN) and when the char will equal "\t" you would have to list files in current directory with php functions and check witch paths are matching to what user have written till now. So you will basically have to re-implement fgets adding magic autocompletion feature.
But instead of doing this and implementing your own shell I guess it would be far more better to make the folder location a script argument:
<?php
if(empty($argv[1])) die("usage: php script.php folderpath");
echo "your folder is located at:" . $argv[1];
So you could call it from windows shell like:
#php script.php
usage: php script.php folderpath
#php script.php foldername
your folder is located at: foldername
And then the autocompletion feature will work.

Related

PHP How to get the library to which a function belongs? [duplicate]

How can I find out in which file and line a given function was defined?
You could also do this in PHP itself:
$reflFunc = new ReflectionFunction('function_name');
print $reflFunc->getFileName() . ':' . $reflFunc->getStartLine();
Either use a IDE that allows doing so (I would recomend Eclipse PDT), or you can allways grep it if on Linux, or using wingrep. In Linux it would be something like:
grep -R "function funName" *
from within the root folder of the project.
I like Tom's solution, so I thought I could share a bit more tricks with ReflectionFunction (it should work on every PHP 5):
one-liner to print the filename:
print (new ReflectionFunction("foo"))->getFileName();
Please note that it won't show you the location for internal functions (such as _), but it still can print the API for it as below.
to print the definition and parameters of the function:
print new ReflectionFunction("foo");
Example:
$ php -r 'print new ReflectionFunction("_");'
Function [ <internal:gettext> function _ ] {
- Parameters [1] {
Parameter #0 [ <required> $msgid ]
}
}
If you use an IDE like Netbeans, you can CTRL+Click the function use and it will take you to where it is defined, assuming the file is within the project folder you defined.
There's no code or function to do this though.
I assume that by "described" you mean "defined". For this, you ideally need a decent IDE that can do it.
Heres a basic function that will scan your entire project files for a specific string and tell you which file it is in and which char position it starts at using only basic php.
Hope this helps someone...
<?php
$find="somefunction()";
echo findString('./ProjectFolderOrPath/',$find);
function findString($path,$find){
$return='';
ob_start();
if ($handle = opendir($path)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if(is_dir($path.'/'.$file)){
$sub=findString($path.'/'.$file,$find);
if(isset($sub)){
echo $sub.PHP_EOL;
}
}else{
$ext=substr(strtolower($file),-3);
if($ext=='php'){
$filesource=file_get_contents($path.'/'.$file);
$pos = strpos($filesource, $find);
if ($pos === false) {
continue;
} else {
echo "The string '$find' was found in the file '$path/$file and exists at position $pos<br />";
}
}else{
continue;
}
}
}
}
closedir($handle);
}
$return = ob_get_contents();
ob_end_clean();
return $return;
}
?>
another way to check where does the function defined, try to redefine the function, PHP error system will simply returns an error told you where the function previously defined
You'll need an IDE that supports "Open Function Declaration" functionality. A good for for php is Eclipse PDT.
To look for the function definition, highlight the function name, hold CTRL + Click on the name.

converting a php function into a bash string

I'm trying to write a bash script that adds a line into a php function like this:
public function register()
{
$this->app->bind('App\Repositories\Corporate\CorporateContract',
'App\Repositories\Corporate\EloquentCorporateRepository');
}
Here's my code:
function bindContractToRepository {
sed -i -e '/register()\n/a \ \n\t\t'${repoBinding}' \n\t\t\t\t ' ./app/Providers/${repoName}${provider}.php 2> /dev/null
}
bindContractToRepository
I actually want my code to come inside the function itself like the example at the top.
NB. I can't specify a particular line because the line number varies with different version
In general it is very difficult to detect PHP function boundaries without a parser.
We can do the parser's job in Bash: iterate the code line by line, solve the opening and closing braces etc. until we get the range of lines covered by this function and, finally, replace it with new content. We can do the same using the sed commands (in this case will likely look less readable than an assembly code).
But we already have a PHP parser! Why not use it?
Example
The following PHP CLI script accepts:
PHP input file (where we are going to replace a method/function);
PHP Method/function name
PHP code string for the replacement as a string, or dash(the standard input)
replace-method.php
<?php
function usage($error = false) {
global $argv;
$str = <<<EOS
USAGE: php {$argv[0]} OPTIONS
OPTIONS:
-h, --help Print help message
-i, --input-file Input PHP file
-m, --method PHP function/method name, e.g.:
my_func, MyClass::myMethod
-c, --code The new PHP code including the function/method declaration.
String of code, or dash ('-') meaning the standard input.
EXAMPLE:
php {$argv[0]} -i source/file.php -m 'MyClass::register' -c - <<ENDOFPHP
public function register()
{
echo time();
}
ENDOFPHP
Replaces the code of 'MyClass::register' method with new code from the standard input
in source/file.php.
EOS;
fprintf($error ? STDERR : STDOUT, $str);
exit((int)!$error);
}
if (false === ($opt = getopt('hi:m:c:', ['help', 'input-file:', 'method:', 'code:']))) {
fprintf(STDERR, "Failed to parse options\n");
usage(true);
}
if (isset($opt['h']) || isset($opt['help']))
usage();
// Using PHP7 Null coalescing operator
$file = $opt['i'] ?? $opt['input-file'] ?? null;
if (!file_exists($file)) {
fprintf(STDERR, "File '$file' does not exist\n");
usage(true);
}
$new_code = $opt['c'] ?? $opt['code'] ?? null;
if (!$new_code) {
fprintf(STDERR, "Code option expected\n");
usage(true);
}
if ($new_code == '-')
$new_code = file_get_contents('php://stdin');
$method = $opt['m'] ?? $opt['method'] ?? null;
if (!$method) {
fprintf(STDERR, "Method option expected\n");
usage(true);
}
// You most likely want to include project's autoloading file instead.
// (You might accept it as a CLI argument, too.)
require_once $file;
$rf = strpos($method, '::') ?
new ReflectionMethod($method) :
new ReflectionFunction($method);
$start_line = $rf->getStartLine();
$end_line = $rf->getEndLine();
$lines = file($file);
$code = implode(array_slice($lines, 0, $start_line - 1)) .
$new_code . implode(array_slice($lines, $end_line));
file_put_contents($file, $code);
Suppose we have path/to/file.php with A class and its register method:
<?php
class A
{
public function register()
{
echo 'aaaa';
}
}
We can replace the code of A::register method in a Bash as follows:
php replace-method.php -i path/to/file.php -m 'A::register' -c - <<ENDOFPHP
public function register()
{
echo 'something new';
}
ENDOFPHP
I've used Bash here document for input. You can use any kind of the shell redirection, for instance:
generate_php_code | php 1.php -i file.php -m 'A::register' -c -

PHP shell_exec does not work for two different app version

I am experiencing an interesting strange issue with shell_exec...
Description
I develop PHP web app that uses C++ backend app for calculations. Server is running on linux and I use shell_exec for C++ program execution. I updated version of my C++ app and since then shell_exec doesn't work, but
I've checked both versions of C++ app have 777 rights
Both versions run flawlessly from a console
Both versions were tested for same data
Both versions were tested on two different PCs/webservers with same results
For both versions the webapp PHP frontend is exactly the same
Second version (that can't be launched) runs faster then previous one
Questions
Have you ever experienced a similar problem?
Is it possible that in shell_exec a problem could occur, that during standard execution from console doesn't?
Piece of PHP code
class LauncherManager extends Nette\Object {
private $wwwDir;
private $db;
private $f;
public function __construct($wwwDir, \DibiConnection $db) {
$this->wwwDir = $wwwDir;
$this->db = $db;
$this->f = (new Dao\DaoFactory())->setDb($db);
}
public function execMeasurement($measurementId) {
$this->execGenetrac(" -m $measurementId");
}
public function execSamples($analysisId) {
$this->execGenetrac(" -s $analysisId");
}
public function execAnalysis($analysisId) {
$this->execGenetrac(" -a $analysisId");
}
public function execGenetrac($params) {
// Check path to genetrac can be set
$path = $this->wwwDir . "/genetrac";
$this->checkPathExist($path);
// Check library path
$lib = './lib';
$expl = 'export LD_LIBRARY_PATH="' . $lib . '"';
$this->checkPathExist($path . "/" . $lib);
// Check genetrac executable exist
$this->checkPathExist($path . "/genetrac");
// Launch genetrac with parameters
$this->exec("cd $path; $expl; ./genetrac $params");
}
public function exec($command) {
return shell_exec($command);
}
...
shell_exec returns NULL in two situations:
an error occurs
executed program returns no output
In order to distinguish these situations use exec() instead:
public function exec($command) {
exec($command, $arrOutputLines, $intReturnStatus);
return join("", $arrOutputLines);
}
You can debug this code by var_dump'ing $arrOutputLines and $intReturnStatus (these are the array of lines that your program printed out and the numeric exit status of your program (0 usually means OK, non-zero means error)).

URL parameters when running PHP via CLI

Is there any way I can pass parameters (like Query string in URL, or URL parameters) to a PHP file which is being run via CLI? I need this for some PHP cron jobs which need input from parameters. For example:
$ php /home/abc/www/myphp.php?param1=abc
There are two special variables in every command line interface argc and argv.
argv - array of arguments passed to the script.
argc - the number of command line parameters passed to the script (if run on the command line).
Make script cli.php
<?php
print_r($_SERVER['argv']);
and call it with argument:
$ php cli.php argument1=1
You should get the output looking like:
Array
(
[0] => cli.php
[1] => argument1=1
)
Source: http://www.php.net/manual/en/reserved.variables.server.php
If you are still so demanding to have a single point entry and to be able to process the url query as $_GET make your script act like a router by adding a switch:
if (PHP_SAPI === 'cli')
{
// ... BUILD $_GET array from argv[0]
}
But then - it violates SRP - Single Responsibility Principle! Having that in mind if you're still so demanding to make it work like you stated in the question you can do it like:
if (PHP_SAPI === 'cli')
{
/** ... BUILD from argv[0], by parsing the query string, a new array and
* name it $data or at will
*/
}
else
{
// ... BUILD new $data array from $_GET array
}
After that convert the code to use $data array instead of $_GET
...and have a nice day!
If the underlying code absolutely requires $_GET (and does not rely on other HTTP features) you can write a simple wrapper that abuses the fact that isn't a read-only superglobal:
<?php
// Untested (tweak to your own needs)
foreach($argv as $i){
list($k, $v) = explode('=', $i, 2);
$_GET[$k] = $v;
}
require_once('/home/abc/www/myphp.php');
... and then schedule your proxy instead:
php /path/to/wrapper.php param1=abc
Here's an extracted/rewritten class from my CLI Application library using $_SERVER['argv'] in the same form that linux runs commands (foo.sh --param "value" --marap):
<?php
class ArgumentScanner {
private static $instance;
private $arguments;
public static function get() {
if (empty(self::$instance)) {
self::$instance = new ArgumentScanner();
}
return self::$instance;
}
public function __construct() {
$this->arguments = $this->parseArguments($_SERVER['argv']);
}
public function __isset($argument) {
return isset($this->arguments[$argument]);
}
public function __get($argument) {
return (isset($this->arguments[$argument]) ? $this->arguments[$argument] : null);
}
/**
* Is used to parse the contents of $_SERVER['argv']
* #param array $argumentsRaw The arguments from $_SERVER['argv']
* #return stdClass An object of properties in key-value pairs
*/
private function parseArguments($argumentsRaw) {
$argumentBuffer = '';
foreach ($argumentsRaw as $argument) {
if ($argument[0] == '-') {
$argumentBuffer = substr($argument, ($argument[1] == '-' ? 2 : 1));
$equalSign = strpos($argumentBuffer, '=');
if ($equalSign !== false) {
$argumentKey = substr($argumentBuffer, 0, $equalSign);
$argumentsParsed[$argumentKey] = substr($argumentBuffer, $equalSign + 1);
$argumentBuffer = '';
} else {
$argumentKey = $argumentBuffer;
$argumentsParsed[$argumentKey] = '';
}
} else {
if ($argumentBuffer != '') {
$argumentKey = $argumentBuffer;
$argumentsParsed[$argumentKey] = $argument;
$argumentBuffer = '';
}
}
}
return (object)$argumentsParsed;
}
}
?>
Use:
<?php
$argumentScanner = ArgumentScanner::get();
if (isset($argumentScanner->reset)) {
echo '--reset was passed!';
}
if (isset($argumentScanner->test)) {
echo '--test was passed as ' . $argumentScanner->test . '!';
}
if (isset($argumentScanner->foo)) {
echo '--foo was passed as ' . $argumentScanner->foo . '!';
}
if (isset($argumentScanner->bar)) {
echo '--bar was passed as ' . $argumentScanner->bar . '!';
}
?>
php script.php --foo "bar" --reset -test="hey you!"
Output:
--reset was passed!
--test was passed as hey you!
--foo was passed as bar!
Best solution there would be to refactor and abstract away the business logic, retain the original script as a wrapper for it. Then add a CLI script to wrap the same business logic for the CLI.
That way, you can use the normal CLI parameter handling: http://www.php.net/manual/en/reserved.variables.argv.php
I needed to do the same thing, pass query parameters to a php script to run as a cron job. The script was from a third party and I didn't want to modify or write a new script. The solution was to place the query string parameters in single quotes and replace the question mark with an ampersand. In my case, I pass three parameters.
php /home/abc/www/myphp.php '&param1=abc&param2=def&param3=123'
I found the solution in this post, tried it and it works fine for me.
if (PHP_SAPI === 'cli')
{
parse_str(implode('&', array_slice($argv, 1)), $_GET);
}
This is solution that I use, if running via cli, put vars and values in $_GET,
seems that is working for simple tasks , not sure if work with php getopt etc
try wget and output to null
wget http://localhost/myphp.php?param1=abc -o /dev/null

How can I write to the console in PHP?

Is it possible write a string or log into the console?
What I mean
Just like in JSP, if we print something like system.out.println("some"), it will be there at the console, not at a page.
Or you use the trick from PHP Debug to console.
First you need a little PHP helper function
function debug_to_console($data) {
$output = $data;
if (is_array($output))
$output = implode(',', $output);
echo "<script>console.log('Debug Objects: " . $output . "' );</script>";
}
Then you can use it like this:
debug_to_console("Test");
This will create an output like this:
Debug Objects: Test
Firefox
On Firefox you can use an extension called FirePHP which enables the logging and dumping of information from your PHP applications to the console. This is an addon to the awesome web development extension Firebug.
http://www.studytrails.com/blog/using-firephp-in-firefox-to-debug-php/
Chrome
However if you are using Chrome there is a PHP debugging tool called Chrome Logger or webug (webug has problems with the order of logs).
More recently Clockwork is in active development which extends the Developer Tools by adding a new panel to provide useful debugging and profiling information. It provides out of the box support for Laravel 4 and Slim 2 and support can be added via its extensible API.
Using Xdebug
A better way to debug your PHP would be via Xdebug. Most browsers provide helper extensions to help you pass the required cookie/query string to initialize the debugging process.
Chrome - Xdebug Helper
Firefox - The easiest Xdebug
Opera - Xdebug
Safari - Xdebug Toggler
If you're looking for a simple approach, echo as JSON:
<script>
console.log(<?= json_encode($foo); ?>);
</script>
By default, all output goes to stdout, which is the HTTP response or the console, depending on whether your script is run by Apache or manually on the command line. But you can use error_log for logging and various I/O streams can be written to with fwrite.
Try the following. It is working:
echo("<script>console.log('PHP: " . $data . "');</script>");
As the author of the linked webpage in the popular answer, I would like to add my last version of this simple helper function. It is much more solid.
I use json_encode() to check if the variable type is unnecessary and add a buffer to solve problems with frameworks. There not have a solid return or excessive usage of header().
/**
* Simple helper to debug to the console
*
* #param $data object, array, string $data
* #param $context string Optional a description.
*
* #return string
*/
function debug_to_console($data, $context = 'Debug in Console') {
// Buffering to solve problems frameworks, like header() in this and not a solid return.
ob_start();
$output = 'console.info(\'' . $context . ':\');';
$output .= 'console.log(' . json_encode($data) . ');';
$output = sprintf('<script>%s</script>', $output);
echo $output;
}
Usage
// $data is the example variable, object; here an array.
$data = [ 'foo' => 'bar' ];
debug_to_console($data);`
Screenshot of the result
Also, a simple example as an image to understand it much easier:
$variable = "Variable";
echo "<script>console.log('$variable');</script>";
PHP and JavaScript interaction.
echo
"<div display='none'>
<script type='text/javascript'>
console.log('console log message');
</script>
</div>";
Creates a
<div>
with the
display="none"
so that the div is not displayed, but the
console.log()
function is created in javascript. So you get the message in the console.
I think it can be used --
function jsLogs($data, $isExit) {
$html = "";
$coll;
if (is_array($data) || is_object($data)) {
$coll = json_encode($data);
} else {
$coll = $data;
}
$html = "<script id='jsLogs'>console.log('PHP: ${coll}');</script>";
echo($html);
if ($isExit) exit();
}
# For String
jsLogs("Testing string"); #PHP: Testing string
# For Array
jsLogs(array("test1", "test2")); # PHP: ["test1","test2"]
# For Object
jsLogs(array("test1"=>array("subtest1", "subtest2"))); #PHP: {"test1":["subtest1","subtest2"]}
Some great answers that add more depth; but I needed something simpler and more like the JavaScript console.log() command.
I use PHP in a lot of "gathering data and turn into XML" in Ajax applications. The JavaScript console.log doesn't work in that case; it breaks the XML output.
Xdebug, etc. had similar issues.
My solution in Windows:
Setup a .txt file that is somewhat easily to get to and writable
Set the PHP error_log variable in the .ini file to write to that file
Open the file in Windows File Explorer and open a preview pane for it
Use the error_log('myTest'); PHP command to send messages
This solution is simple and meets my needs most of the time. Standard PHP, and the preview pane automatically updates every time PHP writes to it.
I find this helpful:
function console($data, $priority, $debug)
{
if ($priority <= $debug)
{
$output = '<script>console.log("' . str_repeat(" ", $priority-1) . (is_array($data) ? implode(",", $data) : $data) . '");</script>';
echo $output;
}
}
And use it like:
<?php
$debug = 5; // All lower and equal priority logs will be displayed
console('Important', 1 , $debug);
console('Less Important', 2 , $debug);
console('Even Less Important', 5 , $debug);
console('Again Important', 1 , $debug);
?>
Which outputs in console:
Important
Less Important
Even Less Important
Again Important
And you can switch off less important logs by limiting them using the $debug value.
Short and easy, for arrays, strings or also objects.
function console_log( $data ) {
$output = "<script>console.log( 'PHP debugger: ";
$output .= json_encode(print_r($data, true));
$output .= "' );</script>";
echo $output;
}
For Chrome there is an extension called Chrome Logger allowing to log PHP messages.
The Firefox DevTools even have integrated support for the Chrome Logger protocol.
To enable the logging, you just need to save the 'ChromePhp.php' file in your project. Then it can be used like this:
include 'ChromePhp.php';
ChromePhp::log('Hello console!');
ChromePhp::log($_SERVER);
ChromePhp::warn('something went wrong!');
Example taken from the GitHub page.
The output may then look like this:
function phpconsole($label='var', $x) {
?>
<script type="text/javascript">
console.log('<?php echo ($label)?>');
console.log('<?php echo json_encode($x)?>');
</script>
<?php
}
If you want write to the PHP log file, and not the JavaScript console you can use this:
error_log("This is logged only to the PHP log")
Reference: error_log
I think best solution is to use
error_log(content)
This is output
Edit 2022:
So I’ve discovered way better way and thats file_put_contents("php://stdout", content)
It writes without the logging info
There is also a great Google Chrome extension, PHP Console, with a PHP library that allows you to:
See errors and exceptions in the Chrome JavaScript console and in the notification popups.
Dump any type of variable.
Execute PHP code remotely.
Protect access by password.
Group console logs by request.
Jump to error file:line in your text editor.
Copy error/debug data to the clipboard (for testers).
Here is my solution, the good thing about this one is that you can pass as many params as you like.
function console_log()
{
$js_code = 'console.log(' . json_encode(func_get_args(), JSON_HEX_TAG) .
');';
$js_code = '<script>' . $js_code . '</script>';
echo $js_code;
}
Call it this way
console_log('DEBUG>>', 'Param 1', 'Param 2');
console_log('Console DEBUG:', $someRealVar1, $someVar, $someArray, $someObj);
Now you should be able to see output in your console, happy coding :)
Any of these two are working:
<?php
$five = 5;
$six = 6;
?>
<script>
console.log(<?php echo $five + $six ?>);
</script>
<?php
$five = 5;
$six = 6;
echo("<script>console.log($five + $six);</script>");
?>
I was looking for a way to debug code in a WordPress plugin that I was developing and came across this post.
I took the bits of code that are most applicable to me from other responses and combined these into a function that I can use for debugging WordPress. The function is:
function debug_log($object=null, $label=null, $priority=1) {
$priority = $priority<1? 1: $priority;
$message = json_encode($object, JSON_PRETTY_PRINT);
$label = "Debug" . ($label ? " ($label): " : ': ');
echo "<script>console.log('" . str_repeat("-", $priority-1) . $label . "', " . $message . ");</script>";
}
Usage is as follows:
$txt = 'This is a test string';
$sample_array = array('cat', 'dog', 'pig', 'ant', 'fly');
debug_log($txt, '', 7);
debug_log($sample_array);
If this function is used with WordPress development, the function should be placed in the functions.php file of the child theme and can then be called anywhere in the code.
Clean, fast and simple without useless code:
function consolelog($data) {
echo "<script>console.log('".$data."');</script>";
}
Short and simply with printf and json_encode:
function console_log($data) {
printf('<script>console.log(%s);</script>', json_encode($data));
}
I have abandoned all of the above in favour of Debugger & Logger. I cannot praise it enough!
Just click on one of the tabs at top right, or on the "click here" to expand/hide.
Notice the different "categories". You can click any array to expand/collapse it.
From the web page
Main features:
Show globals variables ($GLOBALS, $_POST, $_GET, $_COOKIE, etc.)
Show PHP version and loaded extensions
Replace PHP built in error handler
Log SQL queries
Monitor code and SQL queries execution time
Inspect variables for changes
Function calls tracing
Code coverage analysis to check which lines of script where executed
Dump of all types of variable
File inspector with code highlighter to view source code
Send messages to JavaScript console (Chrome only), for Ajax scripts
As of 2017, Firebug and hence FirePHP has been disabled.
I wrote some little modifications to the ChromePHP tool to allow seamless migration from FirePHP to Firebug for debugging via the console.
This article explains in clear easy steps
Migrate from FirePHP to ChromePHP in 5 minutes (without breaking existing code)
For Ajax calls or XML / JSON responses, where you don't want to mess with the body, you need to send logs via HTTP headers, then add them to the console with a web extension. This is how FirePHP (no longer available) and QuantumPHP (a fork of ChromePHP) do it in Firefox.
If you have the patience, x-debug is a better option - you get deeper insight into PHP, with the ability to pause your script, see what is going on, then resume the script.
I might be late for a party, but I was looking for an implementation of logging function which:
takes a variable number of comma separated arguments, just like javascript console.log(),
gives a formatted output (not just a serialized string),
is distinguishable from a common javascript console.log().
So the output looks like that:
(The snippet below is tested on php 7.2.11. I'm not sure about its php backward compatibility. It can be an issue for javascript as well (in a term of old browsers), because it creates a trailing comma after console.log() arguments – which is not legal until ES 2017.)
<?php
function console_log(...$args)
{
$args_as_json = array_map(function ($item) {
return json_encode($item);
}, $args);
$js_code = "<script>console.log('%c 💬 log from PHP: ','background: #474A8A; color: #B0B3D6; line-height: 2',";
foreach ($args_as_json as $arg) {
$js_code .= "{$arg},";
}
$js_code .= ")</script>";
echo $js_code;
}
$list = ['foo', 'bar'];
$obj = new stdClass();
$obj->first_name = 'John';
$obj->last_name = 'Johnson';
echo console_log($list, 'Hello World', 123, $obj);
?>
Here's a handy function. It is super simple to use, allows you to pass as many arguments as you like, of any type, and will display the object contents in the browser console window as though you called console.log from JavaScript - but from PHP
Note, you can use tags as well by passing 'TAG-YourTag', and it will be applied until another tag is read, for example, 'TAG-YourNextTag'
/*
* Brief: Print to console.log() from PHP
*
* Description: Print as many strings,arrays, objects, and
* other data types to console.log from PHP.
*
* To use, just call consoleLog($data1, $data2, ... $dataN)
* and each dataI will be sent to console.log - note
* that you can pass as many data as you want an
* this will still work.
*
* This is very powerful as it shows the entire
* contents of objects and arrays that can be
* read inside of the browser console log.
*
* A tag can be set by passing a string that has the
* prefix TAG- as one of the arguments. Everytime a
* string with the TAG- prefix is detected, the tag
* is updated. This allows you to pass a tag that is
* applied to all data until it reaches another tag,
* which can then be applied to all data after it.
*
* Example:
*
* consoleLog('TAG-FirstTag', $data, $data2, 'TAG-SecTag, $data3);
*
* Result:
* FirstTag '...data...'
* FirstTag '...data2...'
* SecTag '...data3...'
*/
function consoleLog(){
if(func_num_args() == 0){
return;
}
$tag = '';
for ($i = 0; $i < func_num_args(); $i++) {
$arg = func_get_arg($i);
if(!empty($arg)){
if(is_string($arg) && strtolower(substr($arg, 0, 4)) === 'tag-'){
$tag = substr($arg, 4);
}else{
$arg = json_encode($arg, JSON_HEX_TAG | JSON_HEX_AMP );
echo "<script>console.log('" . $tag . " " . $arg . "');</script>";
}
}
}
}
NOTE: func_num_args() and func_num_args() are PHP functions for reading a dynamic number of input arguments, and allow this function to have infinitely many console.log requests from one function call.
Though this is an old question, I've been looking for this. Here's my compilation of some solutions answered here and some other ideas found elsewhere to get a one-size-fits-all solution.
CODE :
// Post to browser console
function console($data, $is_error = false, $file = false, $ln = false) {
if(!function_exists('console_wer')) {
function console_wer($data, $is_error = false, $bctr, $file, $ln) {
echo '<div display="none">'.'<script type="text/javascript">'.(($is_error!==false) ? 'if(typeof phperr_to_cns === \'undefined\') { var phperr_to_cns = 1; document.addEventListener("DOMContentLoaded", function() { setTimeout(function(){ alert("Alert. see console."); }, 4000); }); }' : '').' console.group("PHP '.(($is_error) ? 'error' : 'log').' from "+window.atob("'.base64_encode((($file===false) ? $bctr['file'] : $file)).'")'.((($ln!==false && $file!==false) || $bctr!==false) ? '+" on line '.(($ln===false) ? $bctr['line'] : $ln).' :"' : '+" :"').'); console.'.(($is_error) ? 'error' : 'log').'('.((is_array($data)) ? 'JSON.parse(window.atob("'.base64_encode(json_encode($data)).'"))' : '"'.$data.'"').'); console.groupEnd();</script></div>'; return true;
}
}
return #console_wer($data, $is_error, (($file===false && $ln===false) ? array_shift(debug_backtrace()) : false), $file, $ln);
}
//PHP Exceptions handler
function exceptions_to_console($svr, $str, $file, $ln) {
if(!function_exists('severity_tag')) {
function severity_tag($svr) {
$names = [];
$consts = array_flip(array_slice(get_defined_constants(true)['Core'], 0, 15, true));
foreach ($consts as $code => $name) {
if ($svr & $code) $names []= $name;
}
return join(' | ', $names);
}
}
if (error_reporting() == 0) {
return false;
}
if(error_reporting() & $svr) {
console(severity_tag($svr).' : '.$str, true, $file, $ln);
}
}
// Divert php error traffic
error_reporting(E_ALL);
ini_set("display_errors", "1");
set_error_handler('exceptions_to_console');
TESTS & USAGE :
Usage is simple. Include first function for posting to console manually. Use second function for diverting php exception handling. Following test should give an idea.
// Test 1 - Auto - Handle php error and report error with severity info
$a[1] = 'jfksjfks';
try {
$b = $a[0];
} catch (Exception $e) {
echo "jsdlkjflsjfkjl";
}
// Test 2 - Manual - Without explicitly providing file name and line no.
console(array(1 => "Hi", array("hellow")), false);
// Test 3 - Manual - Explicitly providing file name and line no.
console(array(1 => "Error", array($some_result)), true, 'my file', 2);
// Test 4 - Manual - Explicitly providing file name only.
console(array(1 => "Error", array($some_result)), true, 'my file');
EXPLANATION :
The function console($data, $is_error, $file, $fn) takes string or array as first argument and posts it on console using js inserts.
Second argument is a flag to differentiate normal logs against errors. For errors, we're adding event listeners to inform us through alerts if any errors were thrown, also highlighting in console. This flag is defaulted to false.
Third and fourth arguments are explicit declarations of file and line numbers, which is optional. If absent, they're defaulted to using the predefined php function debug_backtrace() to fetch them for us.
Next function exceptions_to_console($svr, $str, $file, $ln) has four arguments in the order called by php default exception handler. Here, the first argument is severity, which we further crosscheck with predefined constants using function severity_tag($code) to provide more info on error.
NOTICE :
Above code uses JS functions and methods that are not available in older browsers. For compatibility with older versions, it needs replacements.
Above code is for testing environments, where you alone have access to the site. Do not use this in live (production) websites.
SUGGESTIONS :
First function console() threw some notices, so I've wrapped them within another function and called it using error control operator '#'. This can be avoided if you didn't mind the notices.
Last but not least, alerts popping up can be annoying while coding. For this I'm using this beep (found in solution : https://stackoverflow.com/a/23395136/6060602) instead of popup alerts. It's pretty cool and possibilities are endless, you can play your favorite tunes and make coding less stressful.
Use:
function console_log($data) {
$bt = debug_backtrace();
$caller = array_shift($bt);
if (is_array($data))
$dataPart = implode(',', $data);
else
$dataPart = $data;
$toSplit = $caller['file'])) . ':' .
$caller['line'] . ' => ' . $dataPart
error_log(end(split('/', $toSplit));
}
in start code...
error_reporting(-1);
ini_set('display_errors', 'On');
it work

Categories