Using Ray with PHP
This page covers how to use Ray with PHP. There are many different methods available, and this page attempts to showcase most of them. See the reference chart for a full list of methods.
#Basic output
To display something in Ray, use the ray() function. It accepts many different data types: strings, arrays, objects, and more.
ray('Hello world'); ray(['a' => 1, 'b' => 2])->color('red'); ray($anObject);
Passing those will look something like this:

The ray() function accepts multiple arguments. There are displayed as separate messages.
ray('as', 'many' , 'arguments', 'as', 'you', 'like');
#Customizing output
Ray has some useful methods that you can use to add more context or differentiate messages from one another.
#Expanding arrays and objects
When sending an array or object to Ray, it will be displayed in a collapsed state.
To open up a node, you can use the expand method.
// will open up the first level of nodes ray($arrayOrObject)->expand(); // will open up the first three levels of nodes ray($arrayOrObject)->expand(3); // will open the node with key named `myKey` ray($arrayOrObject)->expand('myKey'); // open up all nodes with the given names ray($arrayOrObject)->expand('myKey', 'anotherKey'); // you can use dot notation to expand deeper nodes ray($arrayOrObject)->expand('myKey.nestedKey');
You can also use the expandAll() method to expand all levels.
#Using colors
You can colorize things you sent to Ray by using one of the color functions.
ray('this is green')->green(); ray('this is yellow')->yellow(); ray('this is red')->red(); ray('this is blue')->blue(); ray('this is purple')->purple(); ray('this is gray')->gray();

#Using sizes
Ray can display things in different sizes.
ray('small')->small(); ray('regular'); ray('large')->large();

#Adding a label
You can customize the label displayed next to item with the label function.
ray(['John', 'Paul', 'George', 'Ringo'])->label('Beatles');

#Displaying a table
You can send an associative array to Ray with the table function.
ray()->table([ 'First' => 'First value', 'Second' => 'Second value', 'Third' => 'Third value', ]);

As a second argument, you can pass a label that will be displayed next to the table.
ray()->table(['John', 'Paul', 'George', 'Ringo'], 'Beatles');
#Output formats
You can even pass some less common data types to Ray, and they will be properly formatted.
#Working with JSON
Want to display the JSON representation of anything you'd like in Ray? Use toJson. You can provide any value that can
be converted to JSON with json_encode.
ray()->toJson(['a' => 1, 'b' => ['c' => 3]]);

The toJson function can also accept multiple arguments.
// all of these will be displayed in Ray $object = new \stdClass(); $object->company = 'Spatie'; ray()->toJson( ['a' => 1, 'b' => ['c' => 3]], ['d' => ['e' => 5]], $object );
You can send a valid JSON string to Ray with the json function.
It will be displayed nicely and collapsable in Ray.
$jsonString = json_encode(['a' => 1, 'b' => ['c' => 3]]); ray()->json($jsonString);

The json function can also accept multiple valid JSON strings.
// all of these will be displayed in Ray ray()->json($jsonString, $anotherJsonString, $yetAnotherJsonString);
#Working with XML
You can send a valid XML string to Ray with the xml function.
It will be displayed as formatted XML and collapsable in Ray.
$xmlString = '<one><two><three>3</three></two></one>'; ray()->xml($xmlString);
#Working with Carbon instances
Carbon is a popular datetime package. You can send these instances to Ray with carbon().
ray()->carbon(new \Carbon\Carbon());

#Working with files
You can display the contents of any file in Ray with the file function.
ray()->file('somefile.txt');
#Displaying images
To display an image, call the image function and pass a fully-qualified filename, url, or a valid base64-encoded image as its only argument.
ray()->image('https://placekitten.com/200/300'); ray()->image('/home/user/kitten.jpg'); // display base64-encoded images ray()->image('data:image/png;base64,iVBORw0KGgoAAA…truncated'); ray()->image('iVBORw0KGgoAAA…truncated');
#Displaying a link
You can render a clickable link in Ray, by using the link (or url) methods.
ray()->link('spatie.be'); // we'll assume that you meant `https://spatie.be` ray()->link('spatie.be', 'Spatie homepage'); // optionally, you can pass a label ray()->url('myray.app'); // `url` is an alias of `link`
#Rendering HTML
To render a piece of HTML directly in Ray, you can use the html method.
ray()->html('<b>Bold string<b>');
#Displaying text content
To display raw text while preserving whitespace formatting, use the text method. If the text contains HTML, it will be displayed as-is and is not rendered.
ray()->text('<em>this string is html encoded</em>'); ray()->text(' whitespace formatting' . PHP_EOL . ' is preserved as well.');
#Inspecting values
#Display the class name of an object
To quickly send the class name of an object to ray, use the className function.
ray()->className($anObject)
#Displaying the private properties & methods
Using Ray, you can easily see the value of a private property or the result of a private method.
Consider this simple class:
class PrivateClass { private string $privateProperty = 'this is the value of the private property'; private function privateMethod() { return 'this is the result of the private method'; } }
Here's how you can send the value of the private property to Ray.
$privateClass = new PrivateClass(); ray()->invade($privateClass)->privateProperty;
The invade() method can also display the results of private methods in Ray.
$privateClass = new PrivateClass(); ray()->invade($privateClass)->privateMethod();
If you want to colorize the result, simply tack on one of the color methods.
$privateClass = new PrivateClass(); ray()->invade($privateClass)->privateProperty->red(); ray()->invade($privateClass)->privateMethod()->green();
#Showing raw values
When you sent certain values to Ray, such as Carbon instances or Eloquent models, these values will be displayed in nice way. To see all private, protected, and public properties of such values, you can use the raw() method.
$eloquentModel = User::create(['email' => 'john@example.com']); ray(new Carbon, $eloquentModel)); // will be formatted nicely ray()->raw(new Carbon, $eloquentModel) // no custom formatting, all properties will be shown in Ray.
#Showing PHP info
Using phpinfo() you can quickly see some information about your PHP environment.
You can also pass ini options to see the value of those options.
ray()->phpinfo(); ray()->phpinfo('xdebug.enabled', 'default_mimetype');

#Caller & stack trace
#See the caller of a function
Sometimes you want to know where your code is being called. You can quickly determine that by using the caller
function.
ray()->caller();

If you want to see the entire backtrace, use the trace (or backtrace).
ray()->trace();

#Measuring & counting
#Counting execution times
You can display a count of how many times a piece of code was called using count.
Here's an example:
foreach (range(1, 2) as $i) { ray()->count(); foreach (range(1, 4) as $j) { ray()->count(); } }
This is how that looks like in Ray.

Optionally, you can pass a name to count. Ray will display a count of how many times a count with that name was
executed.
Here's an example:
foreach (range(1, 4) as $i) { ray()->count('first'); foreach (range(1, 2) as $j) { ray()->count('first'); ray()->count('second'); } }
You may access the value of a named counter using the counterValue function.
foreach (range(1, 4) as $i) { ray()->count('first'); if (ray()->counterValue('first') === 2) { echo "counter value is two!"; } }
This is how that looks like in Ray.

#Measuring performance and memory usage
You can use the measure function to display runtime and memory usage. When measure is called again, the time between
this and previous call is also displayed.
ray()->measure(); sleep(1); ray()->measure(); sleep(2); ray()->measure();

The measure call optionally accepts a callable. Ray will output the time needed to run the callable and the maximum
memory used.
ray()->measure(function() { sleep(5); });
#Limiting output
#Limiting the number of sent payloads
To limit the number of payloads sent by a particular ray() call, use the limit function. It works well for debugging loops.
foreach (range(1, 10) as $i) { ray()->limit(3)->text("A #{$i}"); // counts to 3 ray()->limit(6)->text("B #{$i}"); // counts to 6 ray()->text("C #{$i}"); // counts to 10 }
If the argument passed to limit() is a negative number or zero, limiting is disabled.
#Using a rate limiter
A rate limiter can help to reduce the amount of sent messages. This would avoid spamming the desktop app, which can be helpful when using Ray in loops.
Ray::rateLimiter()->max(10); // only 10 messages will be sent
Ray::rateLimiter()->perSecond(10); // only 10 messages per second will be sent
To remove the rate limits again
Ray::rateLimiter()->clear();
A message to the desktop app will be sent once to notify the user the rate limit has been reached.
#Sending a payload once
To only send a payload once, use the once function. This is useful for debugging loops.
once() may be called with arguments:
foreach (range(1, 10) as $i) { ray()->once($i); // only sends "1" }
You can also use once without arguments. Any function you chain on once will also only be called once.
foreach (range(1, 10) as $i) { ray()->once()->html("<strong>{$i}</strong>"); // only sends "<strong>1</strong>" }
#Conditional output
#Conditionally showing items
You can conditionally show things using the showIf method. If you pass a truthy value, the item will be displayed.
ray('will be shown')->showIf(true); ray('will not be shown')->showIf(false);
You can also pass a callable to showIf. If the callable returns a truthy value, it will be shown. Otherwise, it will
not.
#Conditionally sending items to Ray
If for any reason you do not want to send payloads to Ray unless a condition is met, use the if() method.
You can call if() in two ways: only with a conditional, or with a conditional and a callback. A conditional can be either a truthy
value or a callable that returns a truthy value.
Note that when if() is called with only a conditional, all following chained methods will only execute if the conditional
is true. When using a callback with if(), all additional chained methods will be called.
foreach(range(1, 100) as $number) { ray()->if($number < 10)->text("value is less than ten: $number")->blue(); ray()->if(function() use ($number) { return $number == 25; })->text("value is twenty-five!")->green(); // display "value: #" for every item, and display // even numbered values as red ray()->text("value: $number") ->if($number % 2 === 0) ->red(); }
You can even chain multiple if() calls without callbacks:
foreach(range(1, 10) as $number) { // display "value: #" for every item, and display even values as red // and odd values as blue, except for 10 -- which is shown with large // text and in green. ray() ->text("value: $number") ->if($number % 2 === 0) ->red() ->if($number % 2 !== 0) ->blue() ->if($number === 10) ->large() ->green(); }
Or chain multiple calls to if() with callbacks that don't affect the chained methods following them:
foreach(range(1, 100) as $number) { // display "value: #" for all items and make each item green. // items less than 20 will have their text changed. // when the value is an even number, the item will be displayed with large text. ray()->text("value: $number") ->if($number < 10, function($ray) use ($number) { $ray->text("value is less than ten: $number"); }) ->if($number >= 10 && $number < 20, function($ray) use ($number) { $ray->text("value is less than 20: $number"); }) ->if($number % 2 === 0, function($ray) { $ray->large(); }) ->green(); }
#Handling exceptions
#Displaying exceptions
You can display information about an Exception in Ray, including a snippet of source code showing where it was thrown.
try { throw new \Exception('test'); } catch(\Exception $e) { ray()->exception($e); }
#Callables and handling exceptions
You can use Ray to handle exceptions using when passing a callable to ray using the catch function. If no exceptions are thrown, the result of the callable is sent to the Ray app.
catch accepts several parameters to customize how and which exceptions are handled. If no parameters are passed, all Exceptions are swallowed and execution continues.
ray($callable)->catch(); // execution will continue.
You can also pass a callable to catch to customize the handling of an Exception. If you typehint the $exception variable, only Exceptions of that type will be handled. PHP 8 union types are supported.
ray($callable)->catch(function(MyException $exception) { // do something with $exception if it is of the MyException type }); ray($callable)->catch(function($exception) { // handle any exception type });
The catch callable also accepts a second, optional parameter - $ray - that provides access to the current instance of the Ray class if you'd like more control over
If you prefer to swallow all exceptions of a given type without specifying a callback, simply pass the Exception class name or names:
ray($callable)->catch(CustomExceptionOne::class); ray($callable)->catch([ CustomExceptionOne::class, CustomExceptionTwo::class, ]);
You can even pass multiple callables and/or classnames as an array to catch and they will be treated as possible handlers for any Exceptions:
ray($callable)->catch([ function(CustomExceptionOne $exception) { // handle CustomExceptionOne exceptions }, function(CustomExceptionTwo $exception) { // handle CustomExceptionTwo exceptions }, \Exception::class, ]);
If you would like to immediately throw any unhandled exceptions from the callable after calling ray, chain the throwExceptions function onto the ray call. If throwExceptions is not chained, it will be called when PHP finishes executing the script or application.
// immediately throw unhandled exceptions ray($callable) ->catch(CustomExceptionOne::class) ->throwExceptions();
After calling catch, you may continue to chain methods that will be called regardless of whether there was an exception handled or not.
#Updating & removing items
#Updating displayed items
You can update values that are already displayed in Ray. To do this, you must hold on the instance returned by the ray
function and call send on it.
Here's an example where you'll see a countdown from 10 to one.
$ray = ray('counting down!'); foreach(range(10, 1) as $number) { sleep(1); $ray->send($number); }
The instance $ray may also be used to add a color or size to items already on display. Here's an example where an
items will change color and size after a second
$ray = ray('a string'); sleep(1); $ray->red()->large()
#Removing items
You can remove an item that is already displayed in Ray. To do this, call the remove function on an instance return by
the ray function.
$ray = ray('will be removed after 1 sec'); sleep(1); $ray->remove();
You can also conditionally remove items with the removeWhen function (or the removeIf alias).
ray('this one will be remove if the number is 2')->removeWhen($number === 2);
removeWhen also accepts a callable.
ray('this one will be remove if the number is 2')->removeWhen(fn() => … // return true to remove the item);
#Execution control
#Pausing execution
You can pause execution of a script by using the pause method.
ray()->pause();

If you press the "Continue" button in Ray, execution will continue. When you press "Stop execution", Ray will throw an exception in your app to halt execution.
If you are using Windows, you must set the maximum execution time to a high value, as the paused time will count against the maximum execution time.
#Halting the PHP process
You can stop the PHP process by calling die.
ray($anything)->die();
Alternatively, you can use the rd function.
rd($anything);
#Flow helpers
#Returning items
To make all methods chainable, the ray() function returns an instance of Spatie\Ray\Ray. To quickly send something
to Ray and have that something return as a value, use the pass function.
ray()->pass($anything) // $anything will be returned
This is handy when, for instance, debugging return values.
You can change
function foo() { return 'return value', }
to
function foo() { return ray()->pass('return value'), }
#Custom functions
In all PHP projects, ray will proxy all calls to the Spatie\Ray\Ray class. This class is macroable: you can dynamically add your own functions to it.
Here's a silly example where the passed value will be displayed in uppercase in the Ray app.
Spatie\Ray\Ray::macro('uppercase', function(string $value) { $uppercasedValue = strtoupper($value); $this->send($uppercasedValue); return $this; }); ray()->uppercase('this string will be displayed uppercase in ray')
If you want add a label next to the item, use sendCustom in your macro.
// Import this at the top of your file use Spatie\Ray\Ray Ray::macro('myCustomFunction', function() { $this->sendCustom('my custom content', 'hey'); }); ray()->myCustomFunction();

#Managing the Ray app
#Creating a new screen
You can use newScreen (or clearScreen) to programmatically create a new screen. Your previous messages are automatically saved and moved to the message archive.
ray()->newScreen();
Optionally, you can give a screen a name:
ray()->newScreen('My debug screen');

You could opt to use newScreen very early on in a request so you'll only see items that were sent to Ray in the
current request. In a Laravel app, a good place for this might be the service provider.
When using PHPUnit to run tests, you might use newScreen to get a new screen each time your run a test to debug some
code.
#Showing and hiding the app
You can show and hide the Ray app via code.
ray()->showApp(); // Ray will be brought to the foreground ray()->hideApp(); // Ray will be hidden
#Enabling & disabling Ray
You can enable and disable sending stuff to Ray with the enable and disable functions.
ray('one'); // will be displayed in ray ray()->disable(); ray('two'); // won't be displayed in ray ray()->enable(); ray('three'); // will be displayed in ray
You can check if Ray is enabled or disabled with the enabled and disabled functions.
ray()->disable(); ray()->enabled(); // false ray()->disabled(); // true ray()->enable(); ray()->enabled(); // true ray()->disabled(); // false
#Fun stuff
#Displaying a notification
You can use Ray to display a system notification.
ray()->notify('This is my notification');
#Shooting confetti
For those times when success is to be celebrated.
ray()->confetti();