collect.js: A Laravel-Like Syntax for JavaScript Arrays
Tags: laravel, php, javascript, webdev
Published: 2023-01-23 10:28:51

## Introduction

[Collect.js](https://collect.js.org) is a JavaScript library by [Daniel Eckermann](https://twitter.com/ecrmnn) that provides a convenient layer over the top of arrays. It offers a near-identical API to [Laravel collections](https://laravel.com/docs/9.x/collections) and makes working with arrays much easier (at least, in my opinion).

If you're anything like me, you're probably jumping between writing PHP code in Laravel and then building the frontend in JavaScript quite often when working on projects. In the past, when working with arrays in JavaScript, I've quite often thought to myself, "It'd be really handy if we just had XYZ method like in Laravel Collections". So, collect.js provides a really cool solution to this problems and bridges this gap by providing an API that is consistent with Laravel's Collections in PHP.

At the time of writing this article, collect.js has over 6.1k starts on GitHub and is being downloaded over 1.1 millions time a month!

In this article, we're going to take a look at collect.js, how to install it, and a few examples of common methods that you'll likely use in your own projects.

## Installation

### Install the Library

To get started with using collect.js, you can install it using NPM by running the following command in your project:

```text
npm install collect.js --save
```

If you're using Yarn, you can also choose to install it by running the following command:

```text
yarn add collect.js
```

Alternatively, if you'd rather just include the library via the CDN, you can add the following script tag to your HTML:

```html
<script src="https://cdnjs.com/libraries/collect.js"></script>
```

### Include the Library

After you've installed the library, you'll then need to include it in your project so that you can use it. Let's take a look at a few examples from the library's documentation on how you can include it.

If you want to include it using `require`:

```js
const collect = require('collect.js');

// You can then use it like so...

collect(products)
    .where('price', '>', 299);
```

Or, if you'd prefer to use `import`:

```js
import collect from 'collect.js';

// You can then use it like so...
  
collect(products)
    .where('price', '>', 299);
```

Or, if you'd prefer to use the underlying class rather than using the `collect()` method:

```js
import { Collection } from 'collect.js';

// You can then use it like so...
  
new Collection(products)
    .where('price', '>', 299);
```

## Examples

Now that you have collect.js included in your project and ready to go, let's take a look at some examples from the documentation of different methods available in the library that you'd likely use in your projects:

### filter

The `filter` method filters the collection using the given callback and only keeps the items that pass the provided truth test.

Example:

```js
const collection = collect([1, 2, 3, 4]);

const filtered = collection.filter((value, key) => value > 2);

// 'filtered' will now only include:

// [3, 4]
```

### reject

The `reject` method is the inverse of the `filter` method. It filters the collection using the given callback and removes any items that pass the provided truth test.

Example:

```js
const collection = collect([1, 2, 3, 4]);

const filtered = collection.reject(value => value > 2);

// 'filtered' will now only include:
  
// [1, 2]
```

### map

The `map` method iterates through the items in the collection and passes them to the provided callback. The callback can be used to modify and then return the item. This method will then return a new collection with the modified items.

Example:

```js
const collection = collect([1, 2, 3, 4, 5]);

const multiplied = collection.map(item => item * 2);

// 'multiplied' will now only include:

// [2, 4, 6, 8, 10]
```

As mentioned in the documentation, it's worth noting that the `map` method returns an entirely new collection and doesn't modify the existing one. If you'd prefer to modify the existing collections, you can use the `transform` method instead.

### firstWhere

The `firstWhere` method returns the first item in the collection that has the given key-value pair.

Example:

```js
const collection = collect([
  { name: 'Regena', age: 12 },
  { name: 'Linda', age: 14 },
  { name: 'Diego', age: 23 },
  { name: 'Linda', age: 84 },
]);

const filtered = collection.firstWhere('name', 'Linda');

// 'filtered' will now only include:

// { name: 'Linda', age: 14 }
```

### sortBy

The `sortBy` method allows you to sort a collection using several different approaches.

Firstly, you can sort a collection using the name of the field like so:

```js
const collection = collect([
  { name: 'Desk', price: 200 },
  { name: 'Chair', price: 100 },
  { name: 'Bookcase', price: 150 },
]);

const sorted = collection.sortBy('price');

// 'sorted' will now be:

// [
//   { name: 'Chair', price: 100 },
//   { name: 'Bookcase', price: 150 },
//   { name: 'Desk', price: 200 },
// ]
```

You can use also dot notation to sort the collection using a nested value like so:

```js
const collection = collect([
  {
    name: 'Desk',
    price: 200,
    manufacturer: {
      name: 'IKEA',
    },
  },
  {
    name: 'Chair',
    price: 100,
    manufacturer: {
      name: 'Herman Miller',
    },
  },
  {
    name: 'Bookcase',
    price: 150,
    manufacturer: {
      name: 'IKEA',
    },
  },
]);

const sorted = collection.sortBy('manufacturer.name');

// 'sorted' will now be:
  
// [
//   {
//     name: 'Chair',
//     price: 100,
//     manufacturer: {
//       name: 'Herman Miller',
//     },
//   },
//   {
//     name: 'Desk',
//     price: 200,
//     manufacturer: {
//       name: 'IKEA',
//     },
//   },
//   {
//     name: 'Bookcase',
//     price: 150,
//     manufacturer: {
//       name: 'IKEA',
//     },
//   },
// ]
```

Alternatively, you can also pass your own custom callback that should be used to sort the items like so:

```js
const collection = collect([
  { name: 'Desk', colors: ['Black', 'Mahogany'] },
  { name: 'Chair', colors: ['Black'] },
  { name: 'Bookcase', colors: ['Red', 'Beige', 'Brown'] },
]);

const sorted = collection.sortBy((product, key) => product.colors.length);

// 'sorted' will now be:

// [
//   { name: 'Chair', colors: ['Black'] },
//   { name: 'Desk', colors: ['Black', 'Mahogany'] },
//   { name: 'Bookcase', colors: ['Red', 'Beige', 'Brown'] },
// ]
```

To see a full list of available methods, you can check out the documentation at [https://collect.js.org](https://collect.js.org).

## Differences Between Laravel Collections and collect.js

Although collect.js provides a similar API to Laravel Collections (in PHP), there are some differences to be aware of that might catch you out.

Laravel performs "loose comparisons" by default when working with items in Collections, and provides several methods that you can use for "strict" type checking. However, in collect.js, these extra "strict" type checking methods aren't implemented. Instead, all the methods (apart from the `where` method) in collect.js perform strict checks by default.

The following methods aren't implemented in collect.js:

- `containsStrict` - you can use `contains` instead
- `duplicatesStrict` - you can use `duplicates` instead
- `uniqueStrict` - you can use `unique` instead
- `whereStrict` - you can use `where` instead
- `whereInStrict` - you can use `whereIn` instead
- `whereNotInStrict` - you can use `whereNotIn` instead

Let's take a look at an example of how to perform a strict comparison using the `where` method. Let's imagine that we want to use the `where` method in a Laravel Collection:

```php
$users = [
    ['name' => 'Ash', 'is_verified' => false],
    ['name' => 'Daniel', 'is_verified' => true],
    ['name' => 'Taylor', 'is_verified' => 'true'],
    ['name' => 'Jeffrey', 'is_verified' => 1],
];

$filtered = collect($items)->where('is_verified', true);
  
// $filtered would now contain the following items:

// ['name' => 'Daniel', 'is_verified' => true]
// ['name' => 'Taylor', 'is_verified' => 'true']
// ['name' => 'Jeffrey', 'is_verified' => 1]
```

As you can see, three of the items are kept because `true` is strictly equal to `true` and loosely equal to `"true"` and `1`.

If we wanted to perform a strict comparison, we could use the `whereStrict` method like so:

```php
$users = [
    ['name' => 'Ash', 'is_verified' => false],
    ['name' => 'Daniel', 'is_verified' => true],
    ['name' => 'Taylor', 'is_verified' => 'true'],
    ['name' => 'Jeffrey', 'is_verified' => 1],
];

$filtered = collect($items)->whereStrict('is_verified', true);
  
// $filtered would now contain the following item:

// ['name' => 'Daniel', 'is_verified' => true]
```

As you can see, we're only left with a single item because only strict comparisons were used.

If we wanted to use `where` in collect.js, we could write something like this:

```js
const items = [
    {name: 'Ash', is_verified: false},
    {name: 'Daniel', is_verified: true},
    {name: 'Taylor', is_verified: 'true'},
    {name: 'Jeffrey', is_verified: 1},
];

const filtered = collect(items).where('is_verified', true);
  
// 'filtered' would now contain the following items:
  
// {name: 'Daniel', is_verified: true}
// {name: 'Taylor', is_verified: 'true'}
// {name: 'Jeffrey', is_verified: 1}
```

If we wanted to perform a strict comparison (similar to the Collection's `whereStrict` method), then we could use the `where` method like so:

```js
const items = [
    {name: 'Ash', is_verified: false},
    {name: 'Daniel', is_verified: true},
    {name: 'Taylor', is_verified: 'true'},
    {name: 'Jeffrey', is_verified: 1},
];

const filtered = collect(items).where('is_verified', '===', true);
  
// 'filtered' would now contain the following items:
  
// {name: 'Daniel', is_verified: true}
```

As you can see in the example above, we've passed a `===` to the method as the second parameter, and this will be used as the operator when comparing filtering items.

## Conclusion

Hopefully, this post should have given you a brief look at how you can use collect.js to use a Laravel-like syntax when handling arrays in JavaScript.

If you enjoyed reading this post, I'd love to hear about it. Likewise, if you have any feedback to improve the future ones, I'd also love to hear that too.

You might also be interested in checking out my 220+ page ebook "[Battle Ready Laravel](https://battle-ready-laravel.com)" which covers similar topics in more depth.

If you're interested in getting updated each time I publish a new post, feel free to [sign up for my newsletter](https://ashallendesign.co.uk/blog).

Keep on building awesome stuff! 🚀