I would like to display processing progress using a simple series of dots. This is easy in the browser, just do echo '.' and it goes on the same line, but how do I do this on the same line when sending data to the artisan commandline?
Each subsequent call to $this->info('.') puts the dot on a new line.
The method info uses writeln, it adds a newline at the end, you need to use write instead.
//in your command
$this->output->write('my inline message', false);
$this->output->write('my inline message continues', false);
Probably a little bit of topic, since you want a series of dots only. But you can easily present a progress bar in artisan commands using built in functionality in Laravel.
Declare a class variable like this:
protected $progressbar;
And initialize the progress bar like this, lets say in fire() method:
$this->progressbar = $this->getHelperSet()->get('progress');
$this->progressbar->start($this->output, Model::count());
And then do something like this:
foreach (Model::all() as $instance)
{
$this->progressbar->advance(); //do stuff before or after this
}
And finilize the progress when done by calling this:
$this->progressbar->finish();
Update: For Laravel 5.1+ The simpler syntax is even more convenient:
Initialize $bar = $this->output->createProgressBar(count($foo));
Advance $bar->advance();
Finish $bar->finish();
If you look at the source, you will see that $this->info is actually just a shortcut for $this->output->writeln: Source.
You could use $this->output->write('<info>.</info>') to make it inline.
If you find yourself using this often you can make your own helper method like:
public function inlineInfo($string)
{
$this->output->write("<info>$string</info>");
}
Related
I was writing a very basic test for a Laravel Artisan Console Command, like this:
$this->artisan("my-command", ["--some-option" => "some-value"])
->expectsOutput("the expected output");
The test didn't pass. I got really troubled because "the expected output" was exactly what the command was outputting when executed mannualy.
But that's ok, I just have to inspect what the command output actually is when executed through automated tests, right? But wait, how do I do that?
I tried the following:
$output = new BufferedConsoleOutput();
Artisan::call("my-command", ["--some-option", "some-value"], $output);
// dd($output->fetch()
$this->assertTrue($output->fetch() === "the expected output");
But $output->fetch() seems to be always empty.
In brief: How do I print the actual output of a Laravel command in the context of a test?
This isn't something I would want to set up and leave in your tests, but if you prevent Laravel from mocking the console output, you can capture it for inspection.
Assuming you have this test that fails:
public function testStuffDoesntBreak(): void
{
$this->artisan("my-command", ["--some-option" => "some-value"])
->expectsOutput("the expected output");
}
You can rewrite it to this:
use Illuminate\Support\Facades\Artisan;
...
public function testStuffDoesntBreak(): void
{
$this->withoutMockingConsoleOutput()
->artisan("my-command", ["--some-option" => "some-value"]);
// capture the text output from the command
$result = Artisan::output();
// use standard text assertions
$this->assertEquals("the expected output", $result);
}
When you've disabled console mocking, the artisan() method stops being fluent and instead returns the exit code of the command. But it does allow the Artisan facade to access its output. Whether you want to rewrite tests or just change them on the fly in case of an error is personal preference. I've done the latter, as I'd rather not miss out on features like expectsTable().
You may wonder why I would want to do this. I'm trying to debug PHP performance on an embedded system. Don't have access to any kind of tools on the device.
I was thinking if I could just do a simple microseconds calculation on every call, it would work.
Is there a way to do it? Essentially wrap all of my functions (not built in php).
This wouldn't be for production of course.
You can use declare(ticks=1000); to run an callback, like:
// you can use this:
declare(ticks=1);
// A function called on each tick event
function tick_handler()
{
debug_backtrace();//get function name
microtime();//get time
}
http://www.php.net/declare
you only have to get the right number e.g. 1000 for your tests cycles
Problem / What I've tried:
Getting the currently used controller and action in Laravel 5 is easy (but not as easy as it should be), however I'm stuck with getting the currently used artisan console command.
To fetch the controller name I do this:
$route = Route::getRoutes()->match(Request::capture());
$listAction = explode('\\', $route->getActionName());
$rawAction = end($listAction);
// controller name and action in a simple array
$controllerAndAction = explode('#', $rawAction);
But when calling from a console action, it always returns the default index controller's name ("IndexController" or so in Laravel). Does anybody know how to make this ?
By the way I've also worked throught Request::capture() but this still gives no info about the command.
The simplest way is to just to look at the arguments specified on the command line:
if (array_get(request()->server(), 'argv.1') === 'cache:clear') {
// do things
}
Yes, you can use $_SERVER directly, but I like to use the helper functions or the Facades, as those will give you the current data.
I go from the assumption that - during unit tests - the superglobals might not always reflect the currently tested request.
By the way: Obviously can also do array_get(request()->server('argv'), '1') or something alike. (request()->server('argv.1') doesnt work at this point). Or use \Request::server(). Depends on what you like most.
As per the Symfony\Component\Console\Command\Command class, the method to return the name of the command (eg. my:command) is:
$this->getName();
You should use it from within an Artisan command extending Illuminate\Console\Command (default on Artisan commands).
Remember that it will return only the command name and not the available parameters (eg. for the command signature my:command {--with-params=} it will only return my:command).
Reflection might be of help? Try this:
$var = new \ReflectionClass($this);
dd($var);
********* Updated question **************
So I have tried to implement my own AttrDef to HTMLPurifier but it doesn't "take", and I can't debug using die() either.
Here's what I have:
I created Transform.php in the HTMLPurifier/AttrDef/CSS/ directory. The only contents so far is this (I'm only trying to hook it in for now, I will add validating logics once I see that it is in the loop and thus can test it):
<?php
/**
* Validates Transform as defined by CSS.
*/
class HTMLPurifier_AttrDef_CSS_Transform extends HTMLPurifier_AttrDef
{
//basing this off of the color definition so the var is $color for now, may change it to $transform later
public function validate($color, $config, $context) {
return $color;
}
}
I added my file to library/HTMLPurifier.includes.php like this:
require 'HTMLPurifier/AttrDef/CSS/Transform.php';
and to the library/HTMLPurifier.safe-includes.php
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Transform.php';
(not sure about the difference between these two include files above but all AttrDef files seemed to be in both so I added my file to both as well).
Then I try to make use of this new definition by adding this to library/HTMLPurifier/CSSDefinition.php:
// transform
$this->info['transform'] = new HTMLPurifier_AttrDef_CSS_Transform();
It is as if all of my additions were never made, and I can't debug it by putting a die() in my own file either, nothing happens.
So any advice on where I went wrong or how I can debug this is very much appreciated.
*********** addition *******
I also tried a simple bypass by applying the Color-AttrDef to any transform property, in the CSSDefinition.php:
$this->info['transform'] = new HTMLPurifier_AttrDef_CSS_Color();
And I hacked the original Color definition like this:
//TODO: testing ways to bypass
if (strpos($color, 'rotate(') !== false) {
return $color;
}
Not working. Please advice on what I am missing.
You'll need to define your own AttrDef which knows how to parse and validate such definitions. Color should serve as a decent model, since the rgb syntax is similar to matrix.
Is there a short solution to avoid the execution of the "exit" language construct? Otherwise I'll have to execute my function with another PHP-request.
Sample: main.php
echo 'hello world';
doSomething();
updateSomething();
Sample: doSomething.php
function doSomething()
{
$a = 1+1;
exit;
}
Sample: updateSomething.php
function updateSomething()
{
$b = 3+5;
exit;
}
But the second function will never be executed ...is there a simple solution? I've found two existing topics, without a real solution. But maybe there is smart trick for my example?
It's not a real example, in my case the functions represents some complex methods, which are called with ajax reqests without a return statement. Because the method are from a external library, I can't modify the code. And I want to call two methods of this library in one single script, if it's possible :)
And ... I know what return is doing, but in my case I can't modify the code, because it's not my code - it's code from an existing software and I just want to call these existing methods in a custom script. But I can just call one of the methods because of the exit-function in every method and it would be great to call them multiple times.
It's not possible to skip or disable an "exit" command.
If you want to do something before the script stops, you can use shutdown-functions or object-destructors ... but I don't think that's something you're up to, is it?
http://www.php.net/manual/en/function.exit.php
Simple. Remove exit; from the functions.
exit() will terminate execution from the script. You probably want to use return which returns back to the calling code.
The year is 2020 and a way to do what question author wanted to now exists - you can install uopz extension from PECL (version 5.0.2 or above), and use uopz_allow_exit() function to disable exit()'s, like this:
echo 'hello world';
uopz_allow_exit( false );
doSomething();
updateSomething();
uopz_allow_exit( true );
Note, however, that you will need to add this config option into your php.ini file:
uopz.exit = 1
If you dont, then all exit() calls will be disabled by default everywhere unless explicitly enabled by uopz_allow_exit().
It is also worth noting that this config option appeared only in version 6.0.1, which, for me at least, failed to install on PHP 7.0, and worked only on 7.2
Oh, and according to the documentation this extension is supposed to be used for unit testing, not production. Then again, nothing in it says that using this extension in production is discouraged, so it's your call.
From the manual:
Terminates execution of the script.
exit (alias of die) is the final thing the script does. Switch to an alternative use
function doSomething()
{
$a = 1+1;
return true;
}