⚡️ Ray 3.0 launch sale! Discounts and lifetime licenses available for d h m s

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:

screenshot

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();

screenshot

#Using sizes

Ray can display things in different sizes.

ray('small')->small();
ray('regular');
ray('large')->large();

screenshot

#Adding a label

You can customize the label displayed next to item with the label function.

ray(['John', 'Paul', 'George', 'Ringo'])->label('Beatles');

screenshot

#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',
]);

screenshot

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]]);

screenshot

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);

screenshot

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());

screenshot

#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');

screenshot

#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();

screenshot

If you want to see the entire backtrace, use the trace (or backtrace).

ray()->trace();

screenshot

#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.

screenshot

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.

screenshot

#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();

screenshot

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();

screenshot

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();

screenshot

#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');

screenshot

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();
Help us improve this page

Debug without breaking your flow

Ray keeps all your debug output neatly organized in a dedicated desktop app.

Launch sale! Lifetime licenses also available

Ray licenses are valid for 1 year and managed through Spatie. VAT is calculated during checkout.