PHPackages                             ravendb/ravendb-php-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. ravendb/ravendb-php-client

ActiveLibrary[Database &amp; ORM](/categories/database)

ravendb/ravendb-php-client
==========================

RavenDB PHP client

5.2.6(2y ago)96246[2 issues](https://github.com/ravendb/ravendb-php-client/issues)2MITPHPPHP &gt;=8.1CI passing

Since Aug 31Pushed 4mo ago8 watchersCompare

[ Source](https://github.com/ravendb/ravendb-php-client)[ Packagist](https://packagist.org/packages/ravendb/ravendb-php-client)[ Docs](https://github.com/ravendb/ravendb-php-client)[ RSS](/packages/ravendb-ravendb-php-client/feed)WikiDiscussions v5.4 Synced 1mo ago

READMEChangelog (7)Dependencies (10)Versions (9)Used By (2)

PHP client for RavenDB NoSQL Database
=====================================

[](#php-client-for-ravendb-nosql-database)

Installation
------------

[](#installation)

You can install library to your project via [Composer](https://getcomposer.org/)

```
$ composer require ravendb/ravendb-php-client
```

Releases
--------

[](#releases)

- All client versions 5.4.x are fully compatible with and support RavenDB server releases 5.4 and 6.0.
- [Click here](https://github.com/ravendb/ravendb-php-client/releases) to view all Releases and Changelog.

Documentation
-------------

[](#documentation)

This readme provides short examples for the following:

[Getting started](#getting-started),
[Crud example](#crud-example),
[Query documents](#query-documents),
[Attachments](#attachments),
[Time series](#timeseries),
[Revisions](#revisions),
[Suggestions](#suggestions),
[Patching](#advanced-patching),
[Using classes](#using-classes-for-entities),
[PHP usage](#usage-with-php),
[Working with secure server](#working-with-a-secure-server),
[Running tests](#running-tests)

For more information go to the online [RavenDB Documentation](https://ravendb.net/docs/article-page/latest/nodejs/client-api/what-is-a-document-store).

For more information on how to use **RavenDB** with **Laravel**check out the [Raven Laravel Demo Application](https://github.com/ravendb/samples-php-laravel)

Getting started
---------------

[](#getting-started)

1. Require the `DocumentStore` class from the ravendb package

```
use RavenDB\Documents\DocumentStore;
```

2. Initialize the document store (you should have a single DocumentStore instance per application)

```
    $store = new DocumentStore('http://live-test.ravendb.net', 'databaseName');
    $store->initialize();
```

3. Open a session

```
    $session = $store->openSession();
```

4. Call `saveChanges()` when you're done

```
    $user = $session->load('users/1-A'); // Load document
    $user->setPassword(PBKDF2('new password')); // Update data

    $session->saveChanges(); // Save changes
    // Data is now persisted
    // You can proceed e.g. finish web request

```

CRUD example
------------

[](#crud-example)

### Store documents

[](#store-documents)

```
$product = new Product();
$product->setTitle("iPhone X");
$product->setPrice(999.99);
$product->setCurrency("USD");
$product->setStorage(64);
$product->setManufacturer("Apple");
$product->setInStock(true);

$session->store($product, 'products/1-A');
echo $product->id; // products/1-A

$session->saveChanges();
```

> ##### Related tests:
>
> [](#related-tests)
>
> [storing docs with same ID in same session should throw](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TrackEntityTest.php#L80)

### Load documents

[](#load-documents)

```
$product = $session->load(Product::class, 'products/1-A');
echo $product->getTitle(); // iPhone X
echo $product->getId();    // products/1-A
```

### Load documents with include

[](#load-documents-with-include)

```
// users/1
// {
//      "name": "John",
//      "kids": ["users/2", "users/3"]
// }

$session = $store->openSession();

try {
    $user1 = $session
        ->include("kids")
        ->load("users/1");
        // Document users/1 and all docs referenced in "kids"
        // will be fetched from the server in a single request.

    $user2 = $session->load("users/2"); // this won't call server again

    $this->assertNotNull($user1);
    $this->assertNotNull($user2);
    $this->assertEqual(1, $session->advanced()->getNumberOfRequests());
} finally {
    $session->close();
}
```

> ##### Related tests:
>
> [](#related-tests-1)
>
> [can load with includes](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Documents/LoadTest/LoadTest.php#L10)

### Update documents

[](#update-documents)

```
$product = $session->load(Product::class, 'products/1-A');
$product->setInStock(false);
$product->setLastUpdate(new Date());
$session->saveChanges();
// ...
$product = $session->load(Product::class, 'products/1-A');
echo $product->getInStock();    // false
echo $product->getLastUpdate(); // the current date
```

### Delete documents

[](#delete-documents)

1. Using entity

```
$product = $session->load('products/1-A');
$session->delete($product);
$session->saveChanges();

$product = $session->load('products/1-A');
$this->assertNull($product); // null
```

2. Using document ID

```
$session->delete('products/1-A');
```

> ##### Related tests:
>
> [](#related-tests-2)
>
> [delete doc by entity](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/DeleteTest.php#L10)
> [delete doc by ID](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/DeleteTest.php#L38)
> [onBeforeDelete is called before delete by ID](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_15492Test.php#L9)
> [cannot delete untracked entity](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TrackEntityTest.php#L15)
> [loading deleted doc returns null](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TrackEntityTest.php#L37)

Query documents
---------------

[](#query-documents)

1. Use `query()` session method:

Query by collection:

```
$query = $session->query(Product::class, Query::collection('products'));
```

Query by index name:

```
$query = $session->query(Product::class, Query::indexName('productsByCategory'));
```

Query by index:

```
$query = $session->query(Product::class, Products_ByCategory::class);
```

Query by entity type:

```
$query = $session->query(Product::class);
```

2. Build up the query - apply search conditions, set ordering, etc.
    Query supports chaining calls:

```
$query
    ->waitForNonStaleResults()
    ->usingDefaultOperator('AND')
    ->whereEquals('manufacturer', 'Apple')
    ->whereEquals('in_stock', true)
    ->whereBetween('last_update', new DateTime('- 1 week'), new DateTime())
    ->orderBy('price');
```

3. Execute the query to get results:

```
$results = $query->toList(); // get all results
// ...
$firstResult = $query->first(); // gets first result
// ...
$single = $query->single();  // gets single result
```

### Query methods overview

[](#query-methods-overview)

#### selectFields() - projections using a single field

[](#selectfields---projections-using-a-single-field)

```
// RQL
// from users select name

// Query
$userNames = $session->query(User::class)
    ->selectFields("name")
    ->toList();

// Sample results
// John, Stefanie, Thomas
```

> ##### Related tests:
>
> [](#related-tests-3)
>
> [query single property](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L368)
>
> [can\_project\_id\_field](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_14811Test/RavenDB_14811Test.php#L58)

#### selectFields() - projections using multiple fields

[](#selectfields---projections-using-multiple-fields)

```
// RQL
// from users select name, age

// Query
$session->query(User::class)
    ->selectFields([ "name", "age" ])
    ->toList();

// Sample results
// [ [ name: 'John', age: 30 ],
//   [ name: 'Stefanie', age: 25 ],
//   [ name: 'Thomas', age: 25 ] ]
```

> ##### Related tests:
>
> [](#related-tests-4)
>
> [query with projection](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L555)
> [can\_project\_id\_field](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_14811Test/RavenDB_14811Test.php#L58)

#### distinct()

[](#distinct)

```
// RQL
// from users select distinct age

// Query
$session->query(User::class)
    ->selectFields("age")
    ->distinct()
    ->toList();

// Sample results
// [ 30, 25 ]
```

> ##### Related tests:
>
> [](#related-tests-5)
>
> [query distinct](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L611)

#### whereEquals() / whereNotEquals()

[](#whereequals--wherenotequals)

```
// RQL
// from users where age = 30

// Query
$session->query(User::class)
    ->whereEquals("age", 30)
    ->toList();

// Sample results
// [ User {
//    name: 'John',
//    age: 30,
//    kids: [...],
//    registeredAt: 2017-11-10T23:00:00.000Z } ]
```

> ##### Related tests:
>
> [](#related-tests-6)
>
> [where equals](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L784)
> [where not equals](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L817)

#### whereIn()

[](#wherein)

```
// RQL
// from users where name in ("John", "Thomas")

// Query
$session->query(User::class)
    ->whereIn("name", ["John", "Thomas"])
    ->toList();

// Sample results
// [ User {
//     name: 'John',
//     age: 30,
//     registeredAt: 2017-11-10T23:00:00.000Z,
//     kids: [...],
//     id: 'users/1-A' },
//   User {
//     name: 'Thomas',
//     age: 25,
//     registeredAt: 2016-04-24T22:00:00.000Z,
//     id: 'users/3-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-7)
>
> [query with where in](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L416)

#### whereStartsWith() / whereEndsWith()

[](#wherestartswith--whereendswith)

```
// RQL
// from users where startsWith(name, 'J')

// Query
$session->query(User::class)
    ->whereStartsWith("name", "J")
    ->toList();

// Sample results
// [ User {
//    name: 'John',
//    age: 30,
//    kids: [...],
//    registeredAt: 2017-11-10T23:00:00.000Z } ]
```

> ##### Related tests:
>
> [](#related-tests-8)
>
> [query with where clause](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L233)

#### whereBetween()

[](#wherebetween)

```
// RQL
// from users where registeredAt between '2016-01-01' and '2017-01-01'

// Query
$session->query({ collection: "users" })
    ->whereBetween("registeredAt", DateTime::createFromFormat('Y-m-d', '2016-01-01'), DateTime::createFromFormat('Y-m-d', '2017-01-01'))
    ->toList();

// Sample results
// [ User {
//     name: 'Thomas',
//     age: 25,
//     registeredAt: 2016-04-24T22:00:00.000Z,
//     id: 'users/3-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-9)
>
> [query with where between](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L438)

#### whereGreaterThan() / whereGreaterThanOrEqual() / whereLessThan() / whereLessThanOrEqual()

[](#wheregreaterthan--wheregreaterthanorequal--wherelessthan--wherelessthanorequal)

```
// RQL
// from users where age > 29

// Query
$session->query(User::class)
    ->whereGreaterThan("age", 29)
    ->toList();

// Sample results
// [ User {
//   name: 'John',
//   age: 30,
//   registeredAt: 2017-11-10T23:00:00.000Z,
//   kids: [...],
//   id: 'users/1-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-10)
>
> [query with where less than](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L463)
> [query with where less than or equal](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L486)
> [query with where greater than](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L507)
> [query with where greater than or equal](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L532)

#### whereExists()

[](#whereexists)

Checks if the field exists.

```
// RQL
// from users where exists("age")

// Query
$session->query(User::class)
    ->whereExists("kids")
    ->toList();

// Sample results
// [ User {
//   name: 'John',
//   age: 30,
//   registeredAt: 2017-11-10T23:00:00.000Z,
//   kids: [...],
//   id: 'users/1-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-11)
>
> [query where exists](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L997)

#### containsAny() / containsAll()

[](#containsany--containsall)

```
// RQL
// from users where kids in ('Mara')

// Query
$session->query(User::class)
    ->containsAll("kids", ["Mara", "Dmitri"])
    ->toList();

// Sample results
// [ User {
//   name: 'John',
//   age: 30,
//   registeredAt: 2017-11-10T23:00:00.000Z,
//   kids: ["Dmitri", "Mara"]
//   id: 'users/1-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-12)
>
> [queries with contains](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/ContainsTest/ContainsTest.php#L12)

#### search()

[](#search)

Perform full-text search.

```
// RQL
// from users where search(kids, 'Mara')

// Query
$session->query(User::class)
    ->search("kids", "Mara Dmitri")
    ->toList();

// Sample results
// [ User {
//   name: 'John',
//   age: 30,
//   registeredAt: 2017-11-10T23:00:00.000Z,
//   kids: ["Dmitri", "Mara"]
//   id: 'users/1-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-13)
>
> [query search with or](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L636)
> [query\_CreateClausesForQueryDynamicallyWithOnBeforeQueryEvent](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L35)

#### openSubclause() / closeSubclause()

[](#opensubclause--closesubclause)

```
// RQL
// from users where exists(kids) or (age = 25 and name != Thomas)

// Query
$session->query(User::class)
    ->whereExists("kids")
    ->orElse()
    ->openSubclause()
        ->whereEquals("age", 25)
        ->whereNotEquals("name", "Thomas")
    ->closeSubclause()
    ->toList();

// Sample results
// [ User {
//     name: 'John',
//     age: 30,
//     registeredAt: 2017-11-10T23:00:00.000Z,
//     kids: ["Dmitri", "Mara"]
//     id: 'users/1-A' },
//   User {
//     name: 'Stefanie',
//     age: 25,
//     registeredAt: 2015-07-29T22:00:00.000Z,
//     id: 'users/2-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-14)
>
> [working with subclause](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Issues/RavenDB_5669Test/RavenDB_5669Test.php#L44)

#### not()

[](#not)

```
// RQL
// from users where age != 25

// Query
$session->query(User::class)
    ->not()
    ->whereEquals("age", 25)
    ->toList();

// Sample results
// [ User {
//   name: 'John',
//   age: 30,
//   registeredAt: 2017-11-10T23:00:00.000Z,
//   kids: ["Dmitri", "Mara"]
//   id: 'users/1-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-15)
>
> [query where not](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L817)

#### orElse() / andAlso()

[](#orelse--andalso)

```
// RQL
// from users where exists(kids) or age < 30

// Query
$session->query(User::class)
    ->whereExists("kids")
    ->orElse()
    ->whereLessThan("age", 30)
    ->toList();

// Sample results
//  [ User {
//     name: 'John',
//     age: 30,
//     registeredAt: 2017-11-10T23:00:00.000Z,
//     kids: [ 'Dmitri', 'Mara' ],
//     id: 'users/1-A' },
//   User {
//     name: 'Thomas',
//     age: 25,
//     registeredAt: 2016-04-24T22:00:00.000Z,
//     id: 'users/3-A' },
//   User {
//     name: 'Stefanie',
//     age: 25,
//     registeredAt: 2015-07-29T22:00:00.000Z,
//     id: 'users/2-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-16)
>
> [working with subclause](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Issues/RavenDB_5669.ts#L40)

#### usingDefaultOperator()

[](#usingdefaultoperator)

If neither `andAlso()` nor `orElse()` is called then the default operator between the query filtering conditions will be `AND` .
You can override that with `usingDefaultOperator` which must be called before any other where conditions.

```
// RQL
// from users where exists(kids) or age < 29

// Query
$session->query(User::class)
    ->usingDefaultOperator("OR") // override the default 'AND' operator
    ->whereExists("kids")
    ->whereLessThan("age", 29)
    ->toList();

// Sample results
//  [ User {
//     name: 'John',
//     age: 30,
//     registeredAt: 2017-11-10T23:00:00.000Z,
//     kids: [ 'Dmitri', 'Mara' ],
//     id: 'users/1-A' },
//   User {
//     name: 'Thomas',
//     age: 25,
//     registeredAt: 2016-04-24T22:00:00.000Z,
//     id: 'users/3-A' },
//   User {
//     name: 'Stefanie',
//     age: 25,
//     registeredAt: 2015-07-29T22:00:00.000Z,
//     id: 'users/2-A' } ]
```

>

#### orderBy() / orderByDesc() / orderByScore() / randomOrdering()

[](#orderby--orderbydesc--orderbyscore--randomordering)

```
// RQL
// from users order by age

// Query
$session->query(User::class)
    ->orderBy("age")
    ->toList();

// Sample results
// [ User {
//     name: 'Stefanie',
//     age: 25,
//     registeredAt: 2015-07-29T22:00:00.000Z,
//     id: 'users/2-A' },
//   User {
//     name: 'Thomas',
//     age: 25,
//     registeredAt: 2016-04-24T22:00:00.000Z,
//     id: 'users/3-A' },
//   User {
//     name: 'John',
//     age: 30,
//     registeredAt: 2017-11-10T23:00:00.000Z,
//     kids: [ 'Dmitri', 'Mara' ],
//     id: 'users/1-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-17)
>
> [query random order](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L817)
> [order by AlphaNumeric](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L1103)
> [query with boost - order by score](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L1026)

#### take()

[](#take)

Limit the number of query results.

```
// RQL
// from users order by age

// Query
$session->query(User::class)
    ->orderBy("age")
    ->take(2) // only the first 2 entries will be returned
    ->toList();

// Sample results
// [ User {
//     name: 'Stefanie',
//     age: 25,
//     registeredAt: 2015-07-29T22:00:00.000Z,
//     id: 'users/2-A' },
//   User {
//     name: 'Thomas',
//     age: 25,
//     registeredAt: 2016-04-24T22:00:00.000Z,
//     id: 'users/3-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-18)
>
> [query skip take](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L685)

#### skip()

[](#skip)

Skip a specified number of results from the start.

```
// RQL
// from users order by age

// Query
$session->query(User::class)
    ->orderBy("age")
    ->take(1) // return only 1 result
    ->skip(1) // skip the first result, return the second result
    ->toList();

// Sample results
// [ User {
//     name: 'Thomas',
//     age: 25,
//     registeredAt: 2016-04-24T22:00:00.000Z,
//     id: 'users/3-A' } ]
```

> ##### Related tests:
>
> [](#related-tests-19)
>
> [query skip take](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L685)

#### Getting query statistics

[](#getting-query-statistics)

Use the `statistics()` method to obtain query statistics.

```
// Query
$stats = new QueryStatistics();
$results = $session->query(User::class)
    ->whereGreaterThan("age", 29)
    ->statistics($stats)
    ->toList();

// Sample results
// QueryStatistics {
//   isStale: false,
//   durationInMs: 744,
//   totalResults: 1,
//   skippedResults: 0,
//   timestamp: 2018-09-24T05:34:15.260Z,
//   indexName: 'Auto/users/Byage',
//   indexTimestamp: 2018-09-24T05:34:15.260Z,
//   lastQueryTime: 2018-09-24T05:34:15.260Z,
//   resultEtag: 8426908718162809000 }
```

>

#### all() / first() / single() / count()

[](#all--first--single--count)

`all()` - returns all results

`first()` - first result only

`single()` - first result, throws error if there's more entries

`count()` - returns the number of entries in the results (not affected by `take()`)

> ##### Related tests:
>
> [](#related-tests-20)
>
> [query first and single](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L917)
> [query count](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L951)

Attachments
-----------

[](#attachments)

#### Store attachments

[](#store-attachments)

```
$doc = new User();
$doc->setName('John');

// Store a document, the entity will be tracked.
$session->store($doc);

// Get read stream or buffer to store
$fileStream = file_get_contents("../photo.png");

// Store attachment using entity
$session->advanced()->attachments()->store($doc, "photo.png", $fileStream, "image/png");

// OR store attachment using document ID
$session->advanced()->attachments()->store($doc->getId(), "photo.png", $fileStream, "image/png");

// Persist all changes
$session->saveChanges();
```

> ##### Related tests:
>
> [](#related-tests-21)
>
> [can put attachments](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L15)

#### Get attachments

[](#get-attachments)

```
// Get an attachment
$attachment = $session->advanced()->attachments()->get($documentId, "photo.png")

// Attachment.details contains information about the attachment:
//     {
//       name: 'photo.png',
//       documentId: 'users/1-A',
//       contentType: 'image/png',
//       hash: 'MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=',
//       changeVector: '"A:3-K5TR36dafUC98AItzIa6ow"',
//       size: 4579
//     }

// Attachment.data is a Readable.
$fileBytes = $attachment->getData();
file_put_contents('../photo.png', $fileBytes);
```

> ##### Related tests:
>
> [](#related-tests-22)
>
> [can get &amp; delete attachments](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L144)

#### Check if attachment exists

[](#check-if-attachment-exists)

```
$session->advanced()->attachments()->exists($doc->getId(), "photo.png");
// true

$session->advanced()->attachments()->exists($doc->getId(), "not_there.avi");
// false
```

> ##### Related tests:
>
> [](#related-tests-23)
>
> [attachment exists 2](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L419)

#### Get attachment names

[](#get-attachment-names)

```
// Use a loaded entity to determine attachments' names
$session->advanced()->attachments()->getNames($doc);

// Sample results:
// [ { name: 'photo.png',
//     hash: 'MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=',
//     contentType: 'image/png',
//     size: 4579 } ]
```

> ##### Related tests:
>
> [](#related-tests-24)
>
> [get attachment names 2](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L376)

TimeSeries
----------

[](#timeseries)

#### Store time series

[](#store-time-series)

```
$session = $store->openSession();

// Create a document with time series
$session->store(new User(), "users/1");
$tsf = $session->timeSeriesFor("users/1", "heartbeat");

// Append a new time series entry
$tsf->append(new DateTime(), 120);

$session->saveChanges();
```

> ##### Related tests:
>
> [](#related-tests-25)
>
> [canCreateSimpleTimeSeries](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L16)
> [usingDifferentTags](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L244)
> [canStoreAndReadMultipleTimestamps](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L384)
> [canStoreLargeNumberOfValues](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L441)
> [shouldDeleteTimeSeriesUponDocumentDeletion](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L796)

#### Get time series for document

[](#get-time-series-for-document)

```
$session = $store->openSession();

// Get time series for document by time series name
$tsf = $session->timeSeriesFor("users/1", "heartbeat");

// Get all time series entries
$heartbeats = $tsf->get();
```

> ##### Related tests:
>
> [](#related-tests-26)
>
> [canCreateSimpleTimeSeries](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L16)
> [canStoreLargeNumberOfValues](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L441)
> [canRequestNonExistingTimeSeriesRange](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L574)
> [canGetTimeSeriesNames2](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L701)
> [canSkipAndTakeTimeSeries](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L850)

Revisions
---------

[](#revisions)

NOTE: Please make sure revisions are enabled before trying the below.

```
$user = new User();
$user->setName("Marcin");
$user->setAge(30);
$user->setPet("Cat");

$session = $store->openSession();

// Store a document
$session->store($user, "users/1");
$session->saveChanges();

// Modify the document to create a new revision
$user->setName("Roman");
$user->setAge(40);
$session->saveChanges();

// Get revisions
$revisions = $session->advanced()->revisions()->getFor("users/1");

// Sample results:
// [ { name: 'Roman',
//     age: 40,
//     pet: 'Cat',
//     '@metadata': [Object],
//     id: 'users/1' },
//   { name: 'Marcin',
//     age: 30,
//     pet: 'Cat',
//     '@metadata': [Object],
//     id: 'users/1' }
// ]
```

Suggestions
-----------

[](#suggestions)

Suggest options for similar/misspelled terms

```
// Some documents in users collection with misspelled name term
// [ User {
//     name: 'Johne',
//     age: 30,
//     ...
//     id: 'users/1-A' },
//   User {
//     name: 'Johm',
//     age: 31,
//     ...
//     id: 'users/2-A' },
//   User {
//     name: 'Jon',
//     age: 32,
//     ...
//     id: 'users/3-A' },
// ]

// Static index definition
class UsersIndex extends AbstractJavaScriptIndexCreationTask {
    public function __construct() {
        parent::__construct();

        $this->map = "from user in docs.users select new { user.name }";

        // Enable the suggestion feature on index-field 'name'
        $this->suggestion("name");
    }
}

// ...
$session = $store->openSession();

// Query for similar terms to 'John'
// Note: the term 'John' itself will Not be part of the results

$suggestedNameTerms = $session->query(User::class, UsersIndex::class)
    ->suggestUsing(function($x) { return $x->byField("name", "John"); })
    ->execute();

// Sample results:
// { name: { name: 'name', suggestions: [ 'johne', 'johm', 'jon' ] } }
```

Advanced patching
-----------------

[](#advanced-patching)

```
// Increment 'age' field by 1
$session->advanced()->increment("users/1", "age", 1);

// Set 'underAge' field to false
$session->advanced->patch("users/1", "underAge", false);

$session->saveChanges();
```

> ##### Related tests:
>
> [](#related-tests-27)
>
> [can patch](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L19)
> [can patch complex](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L112)
> [can add to array](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L206)
> [can increment](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L368)
> [patchWillUpdateTrackedDocumentAfterSaveChanges](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_11552Test.php#L17)
> [can patch single document](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/PatchTest.php#L17)

Using classes for entities
--------------------------

[](#using-classes-for-entities)

1. Define your model as class. Attributes should be just public properties:

```
class Product {

    public ?string $id = null,
    public string $title = '',
    public int $price = 0,
    public string $currency = 'USD',
    public int $storage = 0,
    public string $manufacturer = '',
    public bool $in_stock = false,
    public ?DateTime $last_update = null

    public function __construct(
        $id = null,
        $title = '',
        $price = 0,
        $currency = 'USD',
        $storage = 0,
        $manufacturer = '',
        $in_stock = false,
        $last_update = null
    ) {
        $this->id = $id;
        $this->title = $title;
        $this->price = $price;
        $this->currency = $currency;
        $this->storage = $storage;
        $this->manufacturer = $manufacturer;
        $this->in_stock = $in_stock;
        $this->last_update = $last_update ?? new DateTime();
    }
}
```

2. To store a document pass its instance to `store()`.
    The collection name will automatically be detected from the entity's class name.

```
use models\Product;

$product = new Product(
  null, 'iPhone X', 999.99, 'USD', 64, 'Apple', true, new Date('2017-10-01T00:00:00'));

$product = $session->store($product);

var_dump($product instanceof Product);                // true
var_dump(str_starts_with($product->id, 'products/')); // true

$session->saveChanges();
```

3. Loading a document

```
$product = $session->load('products/1-A');
var_dump($product instanceof Product); // true
var_dump($product->id);                // products/1-A
```

4. Querying for documents

```
$products = $session->query(Product::class)->toList();

foreach($products as $product) {
  var_dump($product instanceof Product);                // true
  var_dump(str_starts_with($product->id, 'products/')); // true
});
```

>

Usage with PHP
--------------

[](#usage-with-php)

PHP typings are embedded into the package. Make sure to close session when you finish your work with it.

```
// file models/product.php
class Product {
    public ?string $id = null,
    public string $title = '',
    public int $price = 0,
    public string $currency = 'USD',
    public int $storage = 0,
    public string $manufacturer = '',
    public bool $in_stock = false,
    public ?DateTime $last_update = null

    public function __construct(
        $id = null,
        $title = '',
        $price = 0,
        $currency = 'USD',
        $storage = 0,
        $manufacturer = '',
        $in_stock = false,
        $last_update = null
    ) {
        $this->id = $id;
        $this->title = $title;
        $this->price = $price;
        $this->currency = $currency;
        $this->storage = $storage;
        $this->manufacturer = $manufacturer;
        $this->in_stock = $in_stock;
        $this->last_update = $last_update ?? new DateTime();
    }
}

// file app.php
use models\Product;
use RavenDB\Documents\DocumentStore;
use RavenDB\Documents\Session\DocumentSession;

$store = new DocumentStore('url', 'database name');
try {
    $store->initialize();

    $productId = null;

    /** @var DocumentSession $session */
    $session = $store->openSession();
    try {
        $product = new Product(
          null, 'iPhone X', 999.99, 'USD', 64, 'Apple', true, new Date('2017-10-01T00:00:00'));

        $session->store($product);
        $session->saveChanges();

        var_dump($product instanceof Product);                // true
        var_dump(str_starts_with($product->id, 'products/')); // true

        $productId = $product->id;
    } finally {
        $session->close();
    }

    $session = $store->openSession();
    try {
        /** @var Product $product */
        $product = $session->load(Product::class, $productId);

        var_dump($product instanceof Product);                // true
        var_dump($product->id); // products/1-A

        /** @var array $products */
        $products = $session->query(Query::collection('Products'))
                    ->waitForNonStaleResults()
                    ->whereEquals('manufacturer', 'Apple')
                    ->whereEquals('in_stock', true)
                    ->whereBetween('last_update', new DateTime('- 1 week'), new DateTime())
                    ->whereGreaterThanOrEqual('storage', 64)
                    ->toList();

        foreach ($products as $product) {
            var_dump($product instanceof Product);                // true
            var_dump(str_starts_with($product->id, 'products/')); // true
        }

    } finally {
        $session->close();
    }

} finally {
    $store->close();
}
```

Working with a secure server
----------------------------

[](#working-with-a-secure-server)

Your certificate and server certificate should be saved in PEM format to your machine.

1. Create AuthOptions:

```
$authOptions = AuthOptions::pem(
    '../clientCertPath.pem',
    'clientCertPass',
    '../serverCaCertPath.pem'
);
```

2. Pass auth options to `DocumentStore` object:

```
$store = new DocumentStore('url', 'databaseName');
$store->setAuthOptions($authOptions); // use auth options to connect on database
$store->initialize();
```

Running tests
-------------

[](#running-tests)

Clone the repository:

```
git clone https://github.com/ravendb/ravendb-php-client
```

Install dependencies:

```
composer install
```

Run RavenDB server

```
https://a.phptest.development.run
```

Set environment variables.

```
# Set the following environment variables:
#
# - Certificate hostname
# RAVENDB_PHP_TEST_HTTPS_SERVER_URL=https://a.phptest.development.run
#
# RAVENDB_PHP_TEST_CA_PATH=
#
# - Certificate path for tests requiring a secure server:
# RAVENDB_PHP_TEST_CERTIFICATE_PATH=
#
# - Certificate for client
# RAVENDB_TEST_CLIENT_CERT_PATH=
# RAVENDB_TEST_CLIENT_CERT_PASSPHRASE=
#
# - For some tests, Developers licence is required in order to run them all
# RAVEN_LICENSE=
```

Run PHPUnit

```
./vendor/bin/phpunit
```

---

##### Bug Tracker

[](#bug-tracker)

---

##### License

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance46

Moderate activity, may be stable

Popularity23

Limited adoption so far

Community23

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 76.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~151 days

Recently: every ~253 days

Total

9

Last Release

140d ago

PHP version history (2 changes)5.2.0beta1PHP &gt;=7.4

5.2.2PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/8409689b5886c6c2d10ecb0d0f95a2e502a249ce936abad880dfeac9d5a37199?d=identicon)[ravendb](/maintainers/ravendb)

![](https://www.gravatar.com/avatar/1cf337584116ab44ae14206a23b5c7b43c9ee2ae776933d904be594f6b06db68?d=identicon)[alxsabo](/maintainers/alxsabo)

---

Top Contributors

[![alxsabo](https://avatars.githubusercontent.com/u/2970298?v=4)](https://github.com/alxsabo "alxsabo (209 commits)")[![ml054](https://avatars.githubusercontent.com/u/1250431?v=4)](https://github.com/ml054 "ml054 (61 commits)")[![TheDigitalOrchard](https://avatars.githubusercontent.com/u/3195423?v=4)](https://github.com/TheDigitalOrchard "TheDigitalOrchard (2 commits)")[![DejanMilicic](https://avatars.githubusercontent.com/u/507133?v=4)](https://github.com/DejanMilicic "DejanMilicic (1 commits)")[![LielNagar](https://avatars.githubusercontent.com/u/104072448?v=4)](https://github.com/LielNagar "LielNagar (1 commits)")

---

Tags

ravendbphp client

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ravendb-ravendb-php-client/health.svg)

```
[![Health](https://phpackages.com/badges/ravendb-ravendb-php-client/health.svg)](https://phpackages.com/packages/ravendb-ravendb-php-client)
```

###  Alternatives

[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[kimai/kimai

Kimai - Time Tracking

4.6k7.4k1](/packages/kimai-kimai)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
