Laravel 5: Creating Combinations of Elements With crossJoin

April 11, 2018 —John Koster

The crossJoin method can be used to combine the input arrays; the resulting array will contain all of the possible combinations of the input array values.

#Signature

The signature of the crossJoin method is:

1public static function crossJoin(
2 ...$arrays
3);

If you are unfamiliar with the ...$arrays syntax, this is PHP's variable-length argument syntax. It allows developers to accept any number of arguments; these will be passed to the inner function via the $arrays parameter. You can learn more about this syntax by visiting https://php.net/manual/en/functions.arguments.php.

#Example Use

Admittedly, the description of this method can be difficult to grasp reading it the first few times. For the first example, we will look at a way to use this method to create a deck of cards for us. We will do this by creating two input arrays: the first will hold the card suites; the second will hold the card values.

1use Illuminate\Support\Arr;
2 
3$suites = ['Clubs', 'Diamonds', 'Hearts', 'Spades'];
4$cardValues = ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K'];
5 
6$deckOfCards = Arr::crossJoin($suites, $cardValues);

When the above code executes, the $deckOfCards variable would hold an array containing fifty-two items; there will be an entry for each of the suites with their corresponding card values. The first few elements of the resulting array would look like this:

1array [
2 0 => array [
3 0 => "Clubs"
4 1 => "A"
5 ]
6 1 => array [
7 0 => "Clubs"
8 1 => 2
9 ]
10 2 => array [
11 0 => "Clubs"
12 1 => 3
13 ]
14]

While the results are pretty impressive for the amount of code we wrote, let's modify the deck of cards a little bit. What we will do is transform the $deckOfCards so that we have an array containing values with the format <CARD_VALUE> of <CARD_SUITE>. We can do this using PHP's array_map function:

1$newDeckOfCards = array_map(function ($card) {
2 return $card[1] . ' of ' . $card[0];
3}, $deckOfCards);

Now, we will have the same number of items in the $newDeckOfCards array; each value will now be a string. The following is the first few elements of the new array:

1array [
2 0 => "A of Clubs"
3 1 => "2 of Clubs"
4 2 => "3 of Clubs"
5]

While being able to quickly create a deck of cards can be useful, let's take a look at a different example where we use the crossJoin method to generate browser test payloads.

The goal here is to take an array of input element names and an array of common XSS payloads and create a testing payload that we can then use with Laravel Dusk.

1use Illuminate\Support\Arr;
2 
3// The input element names.
4$inputElementNames = [
5 'userName',
6 'password',
7 'firstName',
8 'lastName'
9];
10 
11// Our XSS payloads.
12$xssPayloads = [
13 '<script>prompt(1)</script>',
14 '<script>confirm(1)</script>'
15];
16 
17// Use Arr::crossJoin to create our test payloads.
18$testPayloads = Arr::crossJoin(
19 $inputElementNames,
20 $xssPayloads
21);

We could then use our $testPayloads within a Dusk test like so:

1 
2foreach ($testPayloads as $payload) {
3 $browser->type(
4 $payload[0],
5 $payload[1]
6 );
7 
8 // Do whatever is required to
9 // verify the test status.
10}

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.