{"id":20130451,"url":"https://github.com/ravendb/ravendb-php-client","last_synced_at":"2025-04-09T16:16:00.514Z","repository":{"id":38085528,"uuid":"299257210","full_name":"ravendb/ravendb-php-client","owner":"ravendb","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-18T11:15:11.000Z","size":2325,"stargazers_count":9,"open_issues_count":2,"forks_count":5,"subscribers_count":9,"default_branch":"v5.4","last_synced_at":"2025-04-09T16:15:12.457Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ravendb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-28T09:25:25.000Z","updated_at":"2025-03-18T11:15:18.000Z","dependencies_parsed_at":"2023-02-09T10:32:10.769Z","dependency_job_id":"a25fbe08-d49b-4861-b0f8-70df565b3a41","html_url":"https://github.com/ravendb/ravendb-php-client","commit_stats":{"total_commits":150,"total_committers":3,"mean_commits":50.0,"dds":"0.020000000000000018","last_synced_commit":"6178d8c3ad3fcb6f9bf5fcf6c3637b16f92983b8"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fravendb-php-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fravendb-php-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fravendb-php-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ravendb%2Fravendb-php-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ravendb","download_url":"https://codeload.github.com/ravendb/ravendb-php-client/tar.gz/refs/heads/v5.4","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065283,"owners_count":21041872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T20:38:42.597Z","updated_at":"2025-04-09T16:16:00.506Z","avatar_url":"https://github.com/ravendb.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PHP client for RavenDB NoSQL Database\n\n## Installation\n\nYou can install library to your project via [Composer](https://getcomposer.org/)\n``` bash\n$ composer require ravendb/ravendb-php-client\n```\n\n## Releases\n\n* All client versions 5.4.x are fully compatible with and support RavenDB server releases 5.4 and 6.0.\n\n* [Click here](https://github.com/ravendb/ravendb-php-client/releases) to view all Releases and Changelog.\n\n## Documentation\n\nThis readme provides short examples for the following: \n\n  [Getting started](#getting-started),\u003c!--\n  [Asynchronous call types](#supported-asynchronous-call-types),\n--\u003e  \n  [Crud example](#crud-example),  \n  [Query documents](#query-documents),  \n  [Attachments](#attachments),  \n  [Time series](#timeseries),\u003c!--  \n  [Bulk insert](#bulk-insert),\n  [Changes API](#changes-api),  \n  [Streaming](#streaming),\n--\u003e  \n  [Revisions](#revisions),  \n  [Suggestions](#suggestions),  \n  [Patching](#advanced-patching),\u003c!--\n  [Subscriptions](#subscriptions),  \n  [Using object literals](#using-object-literals-for-entities),\n--\u003e  \n  [Using classes](#using-classes-for-entities),  \n  [PHP usage](#usage-with-php),  \n  [Working with secure server](#working-with-a-secure-server),  \n  [Running tests](#running-tests)  \n\nFor more information go to the online [RavenDB Documentation](https://ravendb.net/docs/article-page/latest/nodejs/client-api/what-is-a-document-store).\n\nFor more information on how to use **RavenDB** with **Laravel** \ncheck out the [Raven Laravel Demo Application](https://github.com/ravendb/samples-php-laravel)\n\n\n## Getting started\n\n1. Require the `DocumentStore` class from the ravendb package\n```php\nuse RavenDB\\Documents\\DocumentStore;\n```\n\n2. Initialize the document store (you should have a single DocumentStore instance per application)\n```php\n    $store = new DocumentStore('http://live-test.ravendb.net', 'databaseName');\n    $store-\u003einitialize();\n```\n\n3. Open a session\n```php\n    $session = $store-\u003eopenSession();\n```\n\n4. Call `saveChanges()` when you're done\n```php\n    $user = $session-\u003eload('users/1-A'); // Load document\n    $user-\u003esetPassword(PBKDF2('new password')); // Update data\n    \n    $session-\u003esaveChanges(); // Save changes\n    // Data is now persisted\n    // You can proceed e.g. finish web request\n    \n```\n\n\u003c!--\n## Supported asynchronous call types\n\nMost methods on the session object are asynchronous and return a Promise.  \nEither use `async \u0026 await` or `.then()` with callback functions.\n\n1. async / await\n```javascript\nconst session = store.openSession();\nlet user = await session.load('users/1-A');\nuser.password = PBKDF2('new password');\nawait session.saveChanges();\n```\n\n2. .then \u0026 callback functions\n```javascript\nsession.load('Users/1-A')\n    .then((user) =\u003e {\n        user.password = PBKDF2('new password');\n    })\n    .then(() =\u003e session.saveChanges())\n    .then(() =\u003e {\n        // here session is complete\n    });\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[async and await](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L55) \u003c/small\u003e  \n\u003e \u003csmall\u003e[then and callbacks](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L72) \u003c/small\u003e\n--\u003e\n\n## CRUD example\n\n### Store documents\n\n```php\n$product = new Product();\n$product-\u003esetTitle(\"iPhone X\");\n$product-\u003esetPrice(999.99);\n$product-\u003esetCurrency(\"USD\");\n$product-\u003esetStorage(64);\n$product-\u003esetManufacturer(\"Apple\");\n$product-\u003esetInStock(true);\n\n$session-\u003estore($product, 'products/1-A');\necho $product-\u003eid; // products/1-A\n\n$session-\u003esaveChanges();\n```\n\n\u003e##### Related tests:\n\u003e \u003c!-- \u003csmall\u003e[store()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/SessionApiTests.ts#L21) \u003c/small\u003e --\u003e  \n\u003e \u003c!-- \u003csmall\u003e[ID generation - session.store()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/IdGeneration.ts#L9) \u003c/small\u003e --\u003e  \n\u003e \u003c!-- \u003csmall\u003e[store document with @metadata](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RDBC_213.ts#L16) \u003c/small\u003e  --\u003e\n\u003e \u003csmall\u003e[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) \u003c/small\u003e \n\n### Load documents\n\n```php\n$product = $session-\u003eload(Product::class, 'products/1-A');\necho $product-\u003egetTitle(); // iPhone X\necho $product-\u003egetId();    // products/1-A\n```\n\n\u003c!-- \u003e ##### Related tests: --\u003e\n\u003c!-- \u003e \u003csmall\u003e[load()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/SessionApiTests.ts#L64) \u003c/small\u003e --\u003e\n\n### Load documents with include\n\n```php\n// users/1\n// {\n//      \"name\": \"John\",\n//      \"kids\": [\"users/2\", \"users/3\"]\n// }\n\n$session = $store-\u003eopenSession();\n\ntry {\n    $user1 = $session\n        -\u003einclude(\"kids\")\n        -\u003eload(\"users/1\");\n        // Document users/1 and all docs referenced in \"kids\"\n        // will be fetched from the server in a single request.\n\n    $user2 = $session-\u003eload(\"users/2\"); // this won't call server again\n\n    $this-\u003eassertNotNull($user1);\n    $this-\u003eassertNotNull($user2);\n    $this-\u003eassertEqual(1, $session-\u003eadvanced()-\u003egetNumberOfRequests());\n} finally {\n    $session-\u003eclose();\n}\n\n\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[can load with includes](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Documents/LoadTest/LoadTest.php#L10) \u003c/small\u003e\n\u003c!-- \u003e \u003csmall\u003e[loading data with include](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L128) \u003c/small\u003e  --\u003e\n\u003c!-- \u003e \u003csmall\u003e[loading data with passing includes](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L148) \u003c/small\u003e --\u003e\n\n### Update documents\n\n```php\n$product = $session-\u003eload(Product::class, 'products/1-A');\n$product-\u003esetInStock(false);\n$product-\u003esetLastUpdate(new Date());\n$session-\u003esaveChanges();\n// ...\n$product = $session-\u003eload(Product::class, 'products/1-A');\necho $product-\u003egetInStock();    // false\necho $product-\u003egetLastUpdate(); // the current date\n```\n\n\u003c!-- \u003e##### Related tests: --\u003e\n\u003c!-- \u003e \u003csmall\u003e[update document](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L170) \u003c/small\u003e --\u003e \n\u003c!-- \u003e \u003csmall\u003e[update document metadata](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RDBC_213.ts#L35) \u003c/small\u003e --\u003e\n\n### Delete documents\n\n1. Using entity\n```php\n$product = $session-\u003eload('products/1-A');\n$session-\u003edelete($product);\n$session-\u003esaveChanges();\n\n$product = $session-\u003eload('products/1-A');\n$this-\u003eassertNull($product); // null\n```\n\n2. Using document ID\n```php\n$session-\u003edelete('products/1-A');\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[delete doc by entity](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/DeleteTest.php#L10) \u003c/small\u003e  \n\u003e \u003csmall\u003e[delete doc by ID](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/DeleteTest.php#L38) \u003c/small\u003e  \n\u003e \u003csmall\u003e[onBeforeDelete is called before delete by ID](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_15492Test.php#L9) \u003c/small\u003e    \n\u003e \u003csmall\u003e[cannot delete untracked entity](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TrackEntityTest.php#L15) \u003c/small\u003e  \n\u003e \u003csmall\u003e[loading deleted doc returns null](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TrackEntityTest.php#L37) \u003c/small\u003e  \n\n## Query documents\n\n1. Use `query()` session method:\n\nQuery by collection:\n```php\n$query = $session-\u003equery(Product::class, Query::collection('products'));\n```\nQuery by index name:\n```php\n$query = $session-\u003equery(Product::class, Query::indexName('productsByCategory'));\n```\nQuery by index:\n```php\n$query = $session-\u003equery(Product::class, Products_ByCategory::class);\n```\nQuery by entity type:\n```php\n$query = $session-\u003equery(Product::class);\n```\n\n2. Build up the query - apply search conditions, set ordering, etc.  \n   Query supports chaining calls:\n```php\n$query\n    -\u003ewaitForNonStaleResults()\n    -\u003eusingDefaultOperator('AND') \n    -\u003ewhereEquals('manufacturer', 'Apple')\n    -\u003ewhereEquals('in_stock', true)\n    -\u003ewhereBetween('last_update', new DateTime('- 1 week'), new DateTime())\n    -\u003eorderBy('price');\n```\n\n3. Execute the query to get results:\n```php\n$results = $query-\u003etoList(); // get all results\n// ...\n$firstResult = $query-\u003efirst(); // gets first result\n// ...\n$single = $query-\u003esingle();  // gets single result \n```\n\n### Query methods overview\n\n#### selectFields() - projections using a single field\n```php\n// RQL\n// from users select name\n\n// Query\n$userNames = $session-\u003equery(User::class)\n    -\u003eselectFields(\"name\")\n    -\u003etoList();\n\n// Sample results\n// John, Stefanie, Thomas\n```\n\n\u003e##### Related tests:\n\u003e \u003c!-- \u003csmall\u003e[projections single field](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L341) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query single property](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L368) \u003c/small\u003e\n\u003e \u003c!-- \u003csmall\u003e[retrieve camel case with projection](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/CustomKeyCaseConventionsTests.ts#L288) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[can_project_id_field](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_14811Test/RavenDB_14811Test.php#L58) \u003c/small\u003e\n\n#### selectFields() - projections using multiple fields\n```php\n// RQL\n// from users select name, age\n\n// Query\n$session-\u003equery(User::class)\n    -\u003eselectFields([ \"name\", \"age\" ])\n    -\u003etoList();\n\n// Sample results\n// [ [ name: 'John', age: 30 ],\n//   [ name: 'Stefanie', age: 25 ],\n//   [ name: 'Thomas', age: 25 ] ]\n```\n\n\u003e##### Related tests:\n\u003e \u003c!-- \u003csmall\u003e[projections multiple fields](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L349) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query with projection](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L555) \u003c/small\u003e\u003c!-- \n\u003e \u003csmall\u003e[retrieve camel case with projection](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/CustomKeyCaseConventionsTests.ts#L288) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[can_project_id_field](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_14811Test/RavenDB_14811Test.php#L58) \u003c/small\u003e \n\n#### distinct()\n```php\n// RQL\n// from users select distinct age\n\n// Query\n$session-\u003equery(User::class)\n    -\u003eselectFields(\"age\")\n    -\u003edistinct()\n    -\u003etoList();\n\n// Sample results\n// [ 30, 25 ]\n```\n\n\u003e##### Related tests:\n\u003e \u003c!-- \u003csmall\u003e[distinct](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L360) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query distinct](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L611) \u003c/small\u003e\n\n#### whereEquals() / whereNotEquals()\n```php\n// RQL\n// from users where age = 30 \n\n// Query\n$session-\u003equery(User::class)\n    -\u003ewhereEquals(\"age\", 30)\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//    name: 'John',\n//    age: 30,\n//    kids: [...],\n//    registeredAt: 2017-11-10T23:00:00.000Z } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[where equals](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L369) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[where equals](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L784) \u003c/small\u003e  \n\u003e \u003csmall\u003e[where not equals](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L817) \u003c/small\u003e  \n\n#### whereIn()\n```php\n// RQL\n// from users where name in (\"John\", \"Thomas\")\n\n// Query\n$session-\u003equery(User::class)\n    -\u003ewhereIn(\"name\", [\"John\", \"Thomas\"])\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//     name: 'John',\n//     age: 30,\n//     registeredAt: 2017-11-10T23:00:00.000Z,\n//     kids: [...],\n//     id: 'users/1-A' },\n//   User {\n//     name: 'Thomas',\n//     age: 25,\n//     registeredAt: 2016-04-24T22:00:00.000Z,\n//     id: 'users/3-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[where in](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L377) \u003c/small\u003e  --\u003e\n\u003e \u003csmall\u003e[query with where in](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L416) \u003c/small\u003e  \n\n#### whereStartsWith() / whereEndsWith()\n```php\n// RQL\n// from users where startsWith(name, 'J')\n\n// Query\n$session-\u003equery(User::class)\n    -\u003ewhereStartsWith(\"name\", \"J\")\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//    name: 'John',\n//    age: 30,\n//    kids: [...],\n//    registeredAt: 2017-11-10T23:00:00.000Z } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003csmall\u003e[query with where clause](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L233) \u003c/small\u003e  \n\n\n#### whereBetween()\n```php\n// RQL\n// from users where registeredAt between '2016-01-01' and '2017-01-01'\n\n// Query\n$session-\u003equery({ collection: \"users\" })\n    -\u003ewhereBetween(\"registeredAt\", DateTime::createFromFormat('Y-m-d', '2016-01-01'), DateTime::createFromFormat('Y-m-d', '2017-01-01'))\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//     name: 'Thomas',\n//     age: 25,\n//     registeredAt: 2016-04-24T22:00:00.000Z,\n//     id: 'users/3-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[where between](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L385) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query with where between](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L438) \u003c/small\u003e  \n\n#### whereGreaterThan() / whereGreaterThanOrEqual() / whereLessThan() / whereLessThanOrEqual()\n```php\n// RQL\n// from users where age \u003e 29\n\n// Query\n$session-\u003equery(User::class)\n    -\u003ewhereGreaterThan(\"age\", 29)\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//   name: 'John',\n//   age: 30,\n//   registeredAt: 2017-11-10T23:00:00.000Z,\n//   kids: [...],\n//   id: 'users/1-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[where greater than](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L393) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query with where less than](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L463) \u003c/small\u003e  \n\u003e \u003csmall\u003e[query with where less than or equal](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L486) \u003c/small\u003e    \n\u003e \u003csmall\u003e[query with where greater than](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L507) \u003c/small\u003e  \n\u003e \u003csmall\u003e[query with where greater than or equal](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L532) \u003c/small\u003e  \n\n#### whereExists()\nChecks if the field exists.\n```php\n// RQL\n// from users where exists(\"age\")\n\n// Query\n$session-\u003equery(User::class)\n    -\u003ewhereExists(\"kids\")\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//   name: 'John',\n//   age: 30,\n//   registeredAt: 2017-11-10T23:00:00.000Z,\n//   kids: [...],\n//   id: 'users/1-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[where exists](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L401) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query where exists](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L997) \u003c/small\u003e  \n\n#### containsAny() / containsAll()\n```php\n// RQL\n// from users where kids in ('Mara')\n\n// Query\n$session-\u003equery(User::class)\n    -\u003econtainsAll(\"kids\", [\"Mara\", \"Dmitri\"])\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//   name: 'John',\n//   age: 30,\n//   registeredAt: 2017-11-10T23:00:00.000Z,\n//   kids: [\"Dmitri\", \"Mara\"]\n//   id: 'users/1-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[where contains any](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L409) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[queries with contains](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/ContainsTest/ContainsTest.php#L12) \u003c/small\u003e  \n\n#### search()\nPerform full-text search.\n```php\n// RQL\n// from users where search(kids, 'Mara')\n\n// Query\n$session-\u003equery(User::class)\n    -\u003esearch(\"kids\", \"Mara Dmitri\")\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//   name: 'John',\n//   age: 30,\n//   registeredAt: 2017-11-10T23:00:00.000Z,\n//   kids: [\"Dmitri\", \"Mara\"]\n//   id: 'users/1-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[search()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L417) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query search with or](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L636) \u003c/small\u003e    \n\u003e \u003csmall\u003e[query_CreateClausesForQueryDynamicallyWithOnBeforeQueryEvent](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L35) \u003c/small\u003e  \n\n#### openSubclause() / closeSubclause()\n```php\n// RQL\n// from users where exists(kids) or (age = 25 and name != Thomas)\n\n// Query\n$session-\u003equery(User::class)\n    -\u003ewhereExists(\"kids\")\n    -\u003eorElse()\n    -\u003eopenSubclause()\n        -\u003ewhereEquals(\"age\", 25)\n        -\u003ewhereNotEquals(\"name\", \"Thomas\")\n    -\u003ecloseSubclause()\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//     name: 'John',\n//     age: 30,\n//     registeredAt: 2017-11-10T23:00:00.000Z,\n//     kids: [\"Dmitri\", \"Mara\"]\n//     id: 'users/1-A' },\n//   User {\n//     name: 'Stefanie',\n//     age: 25,\n//     registeredAt: 2015-07-29T22:00:00.000Z,\n//     id: 'users/2-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[subclause](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L425) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[working with subclause](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Issues/RavenDB_5669Test/RavenDB_5669Test.php#L44) \u003c/small\u003e  \n\n#### not()\n```php\n// RQL\n// from users where age != 25\n\n// Query\n$session-\u003equery(User::class)\n    -\u003enot()\n    -\u003ewhereEquals(\"age\", 25)\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//   name: 'John',\n//   age: 30,\n//   registeredAt: 2017-11-10T23:00:00.000Z,\n//   kids: [\"Dmitri\", \"Mara\"]\n//   id: 'users/1-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[not()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L438) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query where not](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L817) \u003c/small\u003e  \n\n#### orElse() / andAlso()\n```php\n// RQL\n// from users where exists(kids) or age \u003c 30\n\n// Query\n$session-\u003equery(User::class)\n    -\u003ewhereExists(\"kids\")\n    -\u003eorElse()\n    -\u003ewhereLessThan(\"age\", 30)\n    -\u003etoList();\n\n// Sample results\n//  [ User {\n//     name: 'John',\n//     age: 30,\n//     registeredAt: 2017-11-10T23:00:00.000Z,\n//     kids: [ 'Dmitri', 'Mara' ],\n//     id: 'users/1-A' },\n//   User {\n//     name: 'Thomas',\n//     age: 25,\n//     registeredAt: 2016-04-24T22:00:00.000Z,\n//     id: 'users/3-A' },\n//   User {\n//     name: 'Stefanie',\n//     age: 25,\n//     registeredAt: 2015-07-29T22:00:00.000Z,\n//     id: 'users/2-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[orElse](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L447) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[working with subclause](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Issues/RavenDB_5669.ts#L40) \u003c/small\u003e  \n\n#### usingDefaultOperator()\nIf neither `andAlso()` nor `orElse()` is called then the default operator between the query filtering conditions will be `AND` .  \nYou can override that with `usingDefaultOperator` which must be called before any other where conditions.\n```php\n// RQL\n// from users where exists(kids) or age \u003c 29\n\n// Query\n$session-\u003equery(User::class)\n    -\u003eusingDefaultOperator(\"OR\") // override the default 'AND' operator\n    -\u003ewhereExists(\"kids\")\n    -\u003ewhereLessThan(\"age\", 29)\n    -\u003etoList();\n\n// Sample results\n//  [ User {\n//     name: 'John',\n//     age: 30,\n//     registeredAt: 2017-11-10T23:00:00.000Z,\n//     kids: [ 'Dmitri', 'Mara' ],\n//     id: 'users/1-A' },\n//   User {\n//     name: 'Thomas',\n//     age: 25,\n//     registeredAt: 2016-04-24T22:00:00.000Z,\n//     id: 'users/3-A' },\n//   User {\n//     name: 'Stefanie',\n//     age: 25,\n//     registeredAt: 2015-07-29T22:00:00.000Z,\n//     id: 'users/2-A' } ]\n```\n\n\u003c!-- \u003e##### Related tests:  --\u003e\n\u003e \u003c!-- \u003csmall\u003e[set default operator](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L457) \u003c/small\u003e  --\u003e  \n\u003e \u003c!-- \u003csmall\u003e[AND is used when default operator is not set](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RDBC_649.ts#L36) \u003c/small\u003e    --\u003e\n\u003e \u003c!-- \u003csmall\u003e[set default operator to OR](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RDBC_649.ts#L45) \u003c/small\u003e  --\u003e\n\n#### orderBy() / orderByDesc() / orderByScore() / randomOrdering()\n```php\n// RQL\n// from users order by age\n\n// Query\n$session-\u003equery(User::class)\n    -\u003eorderBy(\"age\")\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//     name: 'Stefanie',\n//     age: 25,\n//     registeredAt: 2015-07-29T22:00:00.000Z,\n//     id: 'users/2-A' },\n//   User {\n//     name: 'Thomas',\n//     age: 25,\n//     registeredAt: 2016-04-24T22:00:00.000Z,\n//     id: 'users/3-A' },\n//   User {\n//     name: 'John',\n//     age: 30,\n//     registeredAt: 2017-11-10T23:00:00.000Z,\n//     kids: [ 'Dmitri', 'Mara' ],\n//     id: 'users/1-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[orderBy()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L467) \u003c/small\u003e  --\u003e  \n\u003e \u003c!-- \u003csmall\u003e[orderByDesc()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L477) \u003c/small\u003e   --\u003e \n\u003e \u003csmall\u003e[query random order](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L817) \u003c/small\u003e  \n\u003e \u003csmall\u003e[order by AlphaNumeric](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L1103) \u003c/small\u003e  \n\u003e \u003csmall\u003e[query with boost - order by score](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L1026) \u003c/small\u003e  \n\n#### take()\nLimit the number of query results.\n```php\n// RQL\n// from users order by age\n\n// Query\n$session-\u003equery(User::class)\n    -\u003eorderBy(\"age\") \n    -\u003etake(2) // only the first 2 entries will be returned\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//     name: 'Stefanie',\n//     age: 25,\n//     registeredAt: 2015-07-29T22:00:00.000Z,\n//     id: 'users/2-A' },\n//   User {\n//     name: 'Thomas',\n//     age: 25,\n//     registeredAt: 2016-04-24T22:00:00.000Z,\n//     id: 'users/3-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[take()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L487) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query skip take](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L685) \u003c/small\u003e  \n\u003e \u003c!-- \u003csmall\u003e[canUseOffsetWithCollectionQuery](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Issues/RavenDB_17551.ts#L17) \u003c/small\u003e  --\u003e\n\n#### skip()\nSkip a specified number of results from the start.\n```php\n// RQL\n// from users order by age\n\n// Query\n$session-\u003equery(User::class)\n    -\u003eorderBy(\"age\") \n    -\u003etake(1) // return only 1 result\n    -\u003eskip(1) // skip the first result, return the second result\n    -\u003etoList();\n\n// Sample results\n// [ User {\n//     name: 'Thomas',\n//     age: 25,\n//     registeredAt: 2016-04-24T22:00:00.000Z,\n//     id: 'users/3-A' } ]\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[skip()](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L496) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[query skip take](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L685) \u003c/small\u003e  \n\u003e \u003c!-- \u003csmall\u003e[canUseOffsetWithCollectionQuery](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Issues/RavenDB_17551.ts#L17) \u003c/small\u003e  --\u003e\n\n#### Getting query statistics\nUse the `statistics()` method to obtain query statistics.\n```php\n// Query\n$stats = new QueryStatistics();\n$results = $session-\u003equery(User::class)\n    -\u003ewhereGreaterThan(\"age\", 29)\n    -\u003estatistics($stats)\n    -\u003etoList();\n\n// Sample results\n// QueryStatistics {\n//   isStale: false,\n//   durationInMs: 744,\n//   totalResults: 1,\n//   skippedResults: 0,\n//   timestamp: 2018-09-24T05:34:15.260Z,\n//   indexName: 'Auto/users/Byage',\n//   indexTimestamp: 2018-09-24T05:34:15.260Z,\n//   lastQueryTime: 2018-09-24T05:34:15.260Z,\n//   resultEtag: 8426908718162809000 }\n```\n\n\u003c!-- \u003e##### Related tests:  --\u003e\n\u003e \u003c!-- \u003csmall\u003e[can get stats](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L506) \u003c/small\u003e  --\u003e\n\n#### all() / first() / single() / count()\n`all()` - returns all results\n\n`first()` - first result only\n\n`single()` - first result, throws error if there's more entries\n\n`count()` - returns the number of entries in the results (not affected by `take()`)\n\n\u003e##### Related tests:  \n\u003e \u003csmall\u003e[query first and single](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L917) \u003c/small\u003e    \n\u003e \u003csmall\u003e[query count](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_QueryTest/QueryTest.php#L951) \u003c/small\u003e  \n\n## Attachments\n\n#### Store attachments\n```php\n$doc = new User();\n$doc-\u003esetName('John');\n\n// Store a document, the entity will be tracked.\n$session-\u003estore($doc);\n\n// Get read stream or buffer to store\n$fileStream = file_get_contents(\"../photo.png\");\n\n// Store attachment using entity\n$session-\u003eadvanced()-\u003eattachments()-\u003estore($doc, \"photo.png\", $fileStream, \"image/png\");\n\n// OR store attachment using document ID\n$session-\u003eadvanced()-\u003eattachments()-\u003estore($doc-\u003egetId(), \"photo.png\", $fileStream, \"image/png\");\n\n// Persist all changes\n$session-\u003esaveChanges();\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[store attachment](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L203) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[can put attachments](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L15) \u003c/small\u003e    \n\u003e \u003c!-- \u003csmall\u003e[checkIfHasChangesIsTrueAfterAddingAttachment](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Issues/RavenDB_16985.ts#L17) \u003c/small\u003e  --\u003e  \n\u003e \u003c!-- \u003csmall\u003e[store many attachments and docs with bulk insert](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Attachments/BulkInsertAttachmentsTest.ts#L105) \u003c/small\u003e  --\u003e\n\n#### Get attachments\n```php\n// Get an attachment\n$attachment = $session-\u003eadvanced()-\u003eattachments()-\u003eget($documentId, \"photo.png\")\n\n// Attachment.details contains information about the attachment:\n//     { \n//       name: 'photo.png',\n//       documentId: 'users/1-A',\n//       contentType: 'image/png',\n//       hash: 'MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=',\n//       changeVector: '\"A:3-K5TR36dafUC98AItzIa6ow\"',\n//       size: 4579 \n//     }\n\n// Attachment.data is a Readable.\n$fileBytes = $attachment-\u003egetData();\nfile_put_contents('../photo.png', $fileBytes);\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[get attachment](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L241) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[can get \u0026 delete attachments](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L144) \u003c/small\u003e  \n\n#### Check if attachment exists\n```php\n$session-\u003eadvanced()-\u003eattachments()-\u003eexists($doc-\u003egetId(), \"photo.png\");\n// true\n\n$session-\u003eadvanced()-\u003eattachments()-\u003eexists($doc-\u003egetId(), \"not_there.avi\");\n// false\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[attachment exists](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L258) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[attachment exists 2](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L419) \u003c/small\u003e  \n\n#### Get attachment names\n```php\n// Use a loaded entity to determine attachments' names\n$session-\u003eadvanced()-\u003eattachments()-\u003egetNames($doc);\n\n// Sample results:\n// [ { name: 'photo.png',\n//     hash: 'MvUEcrFHSVDts5ZQv2bQ3r9RwtynqnyJzIbNYzu1ZXk=',\n//     contentType: 'image/png',\n//     size: 4579 } ]\n```\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[get attachment names](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L266) \u003c/small\u003e  --\u003e  \n\u003e \u003csmall\u003e[get attachment names 2](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/Attachments/AttachmentsSessionTest.php#L376) \u003c/small\u003e  \n\n\n## TimeSeries\n\n#### Store time series\n```php\n$session = $store-\u003eopenSession();\n\n// Create a document with time series\n$session-\u003estore(new User(), \"users/1\");\n$tsf = $session-\u003etimeSeriesFor(\"users/1\", \"heartbeat\");\n\n// Append a new time series entry\n$tsf-\u003eappend(new DateTime(), 120);\n\n$session-\u003esaveChanges();\n```\n\n\u003e##### Related tests:  \n\u003e \u003c!-- \u003csmall\u003e[can use time series](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L759) \u003c/small\u003e    --\u003e\n\u003e \u003csmall\u003e[canCreateSimpleTimeSeries](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L16) \u003c/small\u003e    \n\u003e \u003csmall\u003e[usingDifferentTags](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L244) \u003c/small\u003e    \n\u003e \u003csmall\u003e[canStoreAndReadMultipleTimestamps](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L384) \u003c/small\u003e   \n\u003e \u003csmall\u003e[canStoreLargeNumberOfValues](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L441) \u003c/small\u003e    \n\u003e \u003csmall\u003e[shouldDeleteTimeSeriesUponDocumentDeletion](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L796) \u003c/small\u003e  \n\n#### Get time series for document\n```php\n$session = $store-\u003eopenSession();\n\n// Get time series for document by time series name\n$tsf = $session-\u003etimeSeriesFor(\"users/1\", \"heartbeat\");\n\n// Get all time series entries\n$heartbeats = $tsf-\u003eget();\n```\n\n\u003e##### Related tests:  \n\u003e \u003csmall\u003e[canCreateSimpleTimeSeries](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L16) \u003c/small\u003e    \n\u003e \u003csmall\u003e[canStoreLargeNumberOfValues](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L441) \u003c/small\u003e    \n\u003e \u003csmall\u003e[canRequestNonExistingTimeSeriesRange](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L574) \u003c/small\u003e    \n\u003e \u003csmall\u003e[canGetTimeSeriesNames2](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L701) \u003c/small\u003e    \n\u003e \u003csmall\u003e[canSkipAndTakeTimeSeries](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/TimeSeries/TimeSeriesSessionTest.php#L850) \u003c/small\u003e  \n\n\u003c!-- \n## Bulk Insert\n\n```javascript\n// Create a bulk insert instance from the DocumentStore\nconst bulkInsert = store.bulkInsert();\n\n// Store multiple documents\nfor (const name of [\"Anna\", \"Maria\", \"Miguel\", \"Emanuel\", \"Dayanara\", \"Aleida\"]) {\n    const user = new User({ name });\n    await bulkInsert.store(user);\n}\n\n// Sample documents stored:\n// User { name: 'Anna', id: 'users/1-A' }\n// User { name: 'Maria', id: 'users/2-A' }\n// User { name: 'Miguel', id: 'users/3-A' }\n// User { name: 'Emanuel', id: 'users/4-A' }\n// User { name: 'Dayanara', id: 'users/5-A' }\n// User { name: 'Aleida', id: 'users/6-A' }\n\n// Persist the data - call finish\nawait bulkInsert.finish();\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[bulk insert example](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L279) \u003c/small\u003e  \n\u003e \u003csmall\u003e[simple bulk insert should work](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/BulkInsert/BulkInsertsTest.ts#L23) \u003c/small\u003e  \n\u003e \u003csmall\u003e[bulk insert can be aborted](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/BulkInsert/BulkInsertsTest.ts#L95) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can modify metadata with bulk insert](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/BulkInsert/BulkInsertsTest.ts#L136) \u003c/small\u003e\n\n## Changes API\n\nListen for database changes e.g. document changes.\n\n```javascript\n// Subscribe to change notifications\nconst changes = store.changes();\n\n// Subscribe for all documents, or for specific collection (or other database items)\nconst docsChanges = changes.forAllDocuments();\n\n// Handle changes events \ndocsChanges.on(\"data\", change =\u003e {\n    // A sample change data recieved:\n    // { type: 'Put',\n    //   id: 'users/1-A',\n    //   collectionName: 'Users',\n    //   changeVector: 'A:2-QCawZTDbuEa4HUBORhsWYA' }\n});\n\ndocsChanges.on(\"error\", err =\u003e {\n    // handle errors\n})\n\n{\n    const session = store.openSession();\n    await session.store(new User({ name: \"Starlord\" }));\n    await session.saveChanges();\n}\n\n// ...\n// Dispose the changes instance when you're done\nchanges.dispose();\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[listen to changes](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L306) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can obtain single document changes](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Server/Documents/Notifications/ChangesTest.ts#L25) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can obtain all documents changes](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Server/Documents/Notifications/ChangesTest.ts#L93) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can obtain notification about documents starting with](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Server/Documents/Notifications/ChangesTest.ts#L255) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can obtain notification about documents in collection](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Server/Documents/Notifications/ChangesTest.ts#L312) \u003c/small\u003e\n\n## Streaming\n\n#### Stream documents by ID prefix\n```javascript\n// Filter streamed results by passing an ID prefix\n// The stream() method returns a Node.js ReadableStream\nconst userStream = await session.advanced.stream(\"users/\");\n\n// Handle stream events with callback functions\nuserStream.on(\"data\", user =\u003e {\n    // Get only documents with ID that starts with 'users/' \n    // i.e.: User { name: 'John', id: 'users/1-A' }\n});\n\nuserStream.on(\"error\", err =\u003e {\n    // handle errors\n})\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[can stream users by prefix](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L525) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can stream documents starting with](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Core/Streaming/DocumentStreaming.ts#L39) \u003c/small\u003e\n\n#### Stream documents by query\n```javascript\n// Define a query\nconst query = session.query({ collection: \"users\" }).whereGreaterThan(\"age\", 29);\n\nlet streamQueryStats;\n// Call stream() to execute the query, it returns a Node.js ReadableStream.\n// Can get query stats by passing a stats callback to stream() method\nconst queryStream = await session.advanced.stream(query, _ =\u003e streamQueryStats = _);\n\n// Handle stream events with callback functions\nqueryStream.on(\"data\", user =\u003e {\n    // Only documents matching the query are received\n    // These entities are Not tracked by the session\n});\n\n// Can get query stats by using an event listener\nqueryStream.once(\"stats\", queryStats =\u003e {\n    // Sample stats:\n    // { resultEtag: 7464021133404493000,\n    //   isStale: false,\n    //   indexName: 'Auto/users/Byage',\n    //   totalResults: 1,\n    //   indexTimestamp: 2018-10-01T09:04:07.145Z }\n});\n\n// Stream emits an 'end' event when there is no more data to read\nqueryStream.on(\"end\", () =\u003e {\n   // Get info from 'streamQueryStats', the stats object\n   const totalResults = streamQueryStats.totalResults;\n   const indexUsed = streamQueryStats.indexName;\n});\n\nqueryStream.on(\"error\", err =\u003e {\n    // handle errors\n});\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[can stream query and get stats](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L546) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can stream query results](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Core/Streaming/QueryStreaming.ts#L76) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can stream query results with query statistics](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Core/Streaming/QueryStreaming.ts#L140) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can stream raw query results](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Core/Streaming/QueryStreaming.ts#L192) \u003c/small\u003e\n--\u003e\n\n## Revisions\n\nNOTE: Please make sure revisions are enabled before trying the below.\n\n```php\n$user = new User();\n$user-\u003esetName(\"Marcin\");\n$user-\u003esetAge(30);\n$user-\u003esetPet(\"Cat\");\n\n$session = $store-\u003eopenSession();\n\n// Store a document\n$session-\u003estore($user, \"users/1\");\n$session-\u003esaveChanges();\n\n// Modify the document to create a new revision\n$user-\u003esetName(\"Roman\");\n$user-\u003esetAge(40);\n$session-\u003esaveChanges();\n\n// Get revisions\n$revisions = $session-\u003eadvanced()-\u003erevisions()-\u003egetFor(\"users/1\");\n\n// Sample results:\n// [ { name: 'Roman',\n//     age: 40,\n//     pet: 'Cat',\n//     '@metadata': [Object],\n//     id: 'users/1' },\n//   { name: 'Marcin',\n//     age: 30,\n//     pet: 'Cat',\n//     '@metadata': [Object],\n//     id: 'users/1' }\n// ]\n```\n\u003c!--  \n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[can get revisions](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L737) \u003c/small\u003e  \n\u003e \u003csmall\u003e[canGetRevisionsByDate](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RavenDB_11770.ts#L21) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can handle revisions](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/RevisionsTest.ts#L35) \u003c/small\u003e  \n\u003e \u003csmall\u003e[canGetRevisionsByChangeVectors](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/RevisionsTest.ts#L149) \u003c/small\u003e\n\n--\u003e\n\n## Suggestions\n\nSuggest options for similar/misspelled terms\n\n```php\n// Some documents in users collection with misspelled name term\n// [ User {\n//     name: 'Johne',\n//     age: 30,\n//     ...\n//     id: 'users/1-A' },\n//   User {\n//     name: 'Johm',\n//     age: 31,\n//     ...\n//     id: 'users/2-A' },\n//   User {\n//     name: 'Jon',\n//     age: 32,\n//     ...\n//     id: 'users/3-A' },\n// ]\n\n// Static index definition\nclass UsersIndex extends AbstractJavaScriptIndexCreationTask {\n    public function __construct() {\n        parent::__construct();\n                \n        $this-\u003emap = \"from user in docs.users select new { user.name }\";\n        \n        // Enable the suggestion feature on index-field 'name'\n        $this-\u003esuggestion(\"name\"); \n    }\n}\n\n// ...\n$session = $store-\u003eopenSession();\n\n// Query for similar terms to 'John'\n// Note: the term 'John' itself will Not be part of the results\n\n$suggestedNameTerms = $session-\u003equery(User::class, UsersIndex::class)\n    -\u003esuggestUsing(function($x) { return $x-\u003ebyField(\"name\", \"John\"); }) \n    -\u003eexecute();\n\n// Sample results:\n// { name: { name: 'name', suggestions: [ 'johne', 'johm', 'jon' ] } }\n```\n\n\u003c!--  \n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[can suggest](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L581) \u003c/small\u003e  \n\u003e \u003csmall\u003e[canChainSuggestions](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RavenDB_9584.ts#L19) \u003c/small\u003e  \n\u003e \u003csmall\u003e[canUseAliasInSuggestions](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RavenDB_9584.ts#L42) \u003c/small\u003e  \n\u003e \u003csmall\u003e[canUseSuggestionsWithAutoIndex](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Issues/RavenDB_9584.ts#L60) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can suggest using linq](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Suggestions/SuggestionsTest.ts#L39) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can suggest using multiple words](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Suggestions/SuggestionsTest.ts#L78) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can get suggestions with options](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Suggestions/SuggestionsTest.ts#L125) \u003c/small\u003e\n\n--\u003e\n\n## Advanced patching\n\n```php\n// Increment 'age' field by 1\n$session-\u003eadvanced()-\u003eincrement(\"users/1\", \"age\", 1);\n\n// Set 'underAge' field to false\n$session-\u003eadvanced-\u003epatch(\"users/1\", \"underAge\", false);\n\n$session-\u003esaveChanges();\n```\n\n\u003e##### Related tests:    \n\u003e \u003c!-- \u003csmall\u003e[can use advanced.patch](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L708) \u003c/small\u003e  --\u003e\n\u003e \u003csmall\u003e[can patch](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L19) \u003c/small\u003e    \n\u003e \u003csmall\u003e[can patch complex](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L112) \u003c/small\u003e    \n\u003e \u003csmall\u003e[can add to array](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L206) \u003c/small\u003e    \n\u003e \u003csmall\u003e[can increment](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/_FirstClassPatchTest/FirstClassPatchTest.php#L368) \u003c/small\u003e    \n\u003e \u003csmall\u003e[patchWillUpdateTrackedDocumentAfterSaveChanges](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Issues/RavenDB_11552Test.php#L17) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can patch single document](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/PatchTest.php#L17) \u003c/small\u003e   \n\u003e \u003c!-- \u003csmall\u003e[can patch multiple documents](https://github.com/ravendb/ravendb-php-client/blob/282c7bf6d2580ba446e878498d215a38caa67799/tests/Test/Client/PatchTest.php#L89) \u003c/small\u003e  --\u003e\n\n\u003c!--\n\n## Subscriptions\n\n```javascript\n// Create a subscription task on the server\n// Documents that match the query will be send to the client worker upon opening a connection\n\nconst subscriptionName = await store.subscriptions.create({\n    query: \"from users where age \u003e= 30\"\n});\n\n// Open a connection\n// Create a subscription worker that will consume document batches sent from the server\n// Documents are sent from the last document that was processed for this subscription\n\nconst subscriptionWorker = store.subscriptions.getSubscriptionWorker({ subscriptionName });\n\n// Worker handles incoming batches\nsubscriptionWorker.on(\"batch\", (batch, callback) =\u003e {\n    try {\n        // Process the incoming batch items\n        // Sample batch.items:\n        // [ Item {\n        //     changeVector: 'A:2-r6nkF5nZtUKhcPEk6/LL+Q',\n        //     id: 'users/1-A',\n        //     rawResult:\n        //      { name: 'John',\n        //        age: 30,\n        //        registeredAt: '2017-11-11T00:00:00.0000000',\n        //        kids: [Array],\n        //        '@metadata': [Object],\n        //        id: 'users/1-A' },\n        //     rawMetadata:\n        //      { '@collection': 'Users',\n        //        '@nested-object-types': [Object],\n        //        'Raven-Node-Type': 'User',\n        //        '@change-vector': 'A:2-r6nkF5nZtUKhcPEk6/LL+Q',\n        //        '@id': 'users/1-A',\n        //        '@last-modified': '2018-10-18T11:15:51.4882011Z' },\n        //     exceptionMessage: undefined } ]\n        // ...\n\n        // Call the callback once you're done\n        // The worker will send an acknowledgement to the server, so that server can send next batch\n        callback();\n        \n    } catch(err) {\n        // If processing fails for a particular batch then pass the error to the callback\n        callback(err);\n    }\n});\n\nsubscriptionWorker.on(\"error\", err =\u003e {\n   // handle errors\n});\n\n// Subscription event types: \n'batch', 'error', 'end', 'unexpectedSubscriptionError', 'afterAcknowledgment', 'connectionRetry'\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[can subscribe](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L607) \u003c/small\u003e  \n\u003e \u003csmall\u003e[should stream all documents](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Subscriptions/SubscriptionsBasicTest.ts#L143) \u003c/small\u003e  \n\u003e \u003csmall\u003e[should send all new and modified docs](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Subscriptions/SubscriptionsBasicTest.ts#L202) \u003c/small\u003e  \n\u003e \u003csmall\u003e[should respect max doc count in batch](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Subscriptions/SubscriptionsBasicTest.ts#L263) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can disable subscription](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Subscriptions/SubscriptionsBasicTest.ts#L345) \u003c/small\u003e  \n\u003e \u003csmall\u003e[can delete subscription](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/Subscriptions/SubscriptionsBasicTest.ts#L52) \u003c/small\u003e\n\n## Using object literals for entities\n\nTo comfortably use object literals as entities,  \nconfigure the collection name that will be used in the store conventions.\n\nThis must be done *before* calling `initialize()` on the DocumentStore instance,  \nelse, your entities will be created in the *@empty* collection.\n\n```javascript\nconst store = new DocumentStore(urls, database);\n\n// Configure the collection name that will be used\nstore.conventions.findCollectionNameForObjectLiteral = entity =\u003e entity[\"collection\"];\n// ...\nstore.initialize();\n\n// Sample object literal\nconst user = {\n   collection: \"Users\",\n   name: \"John\"\n};\n\nsession = store.openSession();\nawait session.store(user);\nawait session.saveChanges();\n\n// The document will be stored in the 'Users' collection\n```\n\n\u003e##### Related tests:\n\u003e \u003csmall\u003e[using object literals for entities](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/ReadmeSamples.ts#L644) \u003c/small\u003e  \n\u003e \u003csmall\u003e[using object literals](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/SessionApiTests.ts#L108) \u003c/small\u003e  \n\u003e \u003csmall\u003e[handle custom entity naming conventions + object literals](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Ported/BulkInsert/BulkInsertsTest.ts#L220) \u003c/small\u003e\n\n--\u003e\n\n## Using classes for entities\n\n1. Define your model as class. Attributes should be just public properties:\n```php\nclass Product {\n\n    public ?string $id = null,\n    public string $title = '',\n    public int $price = 0,\n    public string $currency = 'USD',\n    public int $storage = 0,\n    public string $manufacturer = '',\n    public bool $in_stock = false,\n    public ?DateTime $last_update = null\n\n    public function __construct(\n        $id = null,\n        $title = '',\n        $price = 0,\n        $currency = 'USD',\n        $storage = 0,\n        $manufacturer = '',\n        $in_stock = false,\n        $last_update = null\n    ) {\n        $this-\u003eid = $id;\n        $this-\u003etitle = $title;\n        $this-\u003eprice = $price;\n        $this-\u003ecurrency = $currency;\n        $this-\u003estorage = $storage;\n        $this-\u003emanufacturer = $manufacturer;\n        $this-\u003ein_stock = $in_stock;\n        $this-\u003elast_update = $last_update ?? new DateTime();\n    }\n}\n```\n\n2. To store a document pass its instance to `store()`.  \n   The collection name will automatically be detected from the entity's class name.\n```php\nuse models\\Product;\n\n$product = new Product(\n  null, 'iPhone X', 999.99, 'USD', 64, 'Apple', true, new Date('2017-10-01T00:00:00'));\n\n$product = $session-\u003estore($product);\n\nvar_dump($product instanceof Product);                // true\nvar_dump(str_starts_with($product-\u003eid, 'products/')); // true\n\n$session-\u003esaveChanges();\n```\n\n3. Loading a document\n```php\n$product = $session-\u003eload('products/1-A');\nvar_dump($product instanceof Product); // true\nvar_dump($product-\u003eid);                // products/1-A\n```\n\n4. Querying for documents\n```php\n$products = $session-\u003equery(Product::class)-\u003etoList();\n\nforeach($products as $product) {\n  var_dump($product instanceof Product);                // true\n  var_dump(str_starts_with($product-\u003eid, 'products/')); // true\n});\n```  \n\n\u003c!-- \u003e##### Related tests:  --\u003e\n\u003e \u003c!-- \u003csmall\u003e[using classes](https://github.com/ravendb/ravendb-nodejs-client/blob/5c14565d0c307d22e134530c8d63b09dfddcfb5b/test/Documents/SessionApiTests.ts#L173) \u003c/small\u003e  --\u003e\n\n## Usage with PHP\n\nPHP typings are embedded into the package. Make sure to close session when you finish your work with it.\n\n```php\n// file models/product.php\nclass Product {\n    public ?string $id = null,\n    public string $title = '',\n    public int $price = 0,\n    public string $currency = 'USD',\n    public int $storage = 0,\n    public string $manufacturer = '',\n    public bool $in_stock = false,\n    public ?DateTime $last_update = null\n    \n    public function __construct(\n        $id = null,\n        $title = '',\n        $price = 0,\n        $currency = 'USD',\n        $storage = 0,\n        $manufacturer = '',\n        $in_stock = false,\n        $last_update = null\n    ) {\n        $this-\u003eid = $id;\n        $this-\u003etitle = $title;\n        $this-\u003eprice = $price;\n        $this-\u003ecurrency = $currency;\n        $this-\u003estorage = $storage;\n        $this-\u003emanufacturer = $manufacturer;\n        $this-\u003ein_stock = $in_stock;\n        $this-\u003elast_update = $last_update ?? new DateTime();\n    }\n}\n\n// file app.php\nuse models\\Product;\nuse RavenDB\\Documents\\DocumentStore;\nuse RavenDB\\Documents\\Session\\DocumentSession;\n\n$store = new DocumentStore('url', 'database name');\ntry {\n    $store-\u003einitialize();\n    \n    $productId = null;\n    \n    /** @var DocumentSession $session */\n    $session = $store-\u003eopenSession();\n    try {\n        $product = new Product(\n          null, 'iPhone X', 999.99, 'USD', 64, 'Apple', true, new Date('2017-10-01T00:00:00'));\n\n        $session-\u003estore($product);\n        $session-\u003esaveChanges();\n        \n        var_dump($product instanceof Product);                // true\n        var_dump(str_starts_with($product-\u003eid, 'products/')); // true\n        \n        $productId = $product-\u003eid;\n    } finally {\n        $session-\u003eclose();    \n    }\n    \n    $session = $store-\u003eopenSession();\n    try {\n        /** @var Product $product */\n        $product = $session-\u003eload(Product::class, $productId);\n        \n        var_dump($product instanceof Product);                // true\n        var_dump($product-\u003eid); // products/1-A\n        \n        /** @var array\u003cProduct\u003e $products */\n        $products = $session-\u003equery(Query::collection('Products'))\n                    -\u003ewaitForNonStaleResults()\n                    -\u003ewhereEquals('manufacturer', 'Apple')\n                    -\u003ewhereEquals('in_stock', true)\n                    -\u003ewhereBetween('last_update', new DateTime('- 1 week'), new DateTime())\n                    -\u003ewhereGreaterThanOrEqual('storage', 64)\n                    -\u003etoList();\n    \n        foreach ($products as $product) {\n            var_dump($product instanceof Product);                // true\n            var_dump(str_starts_with($product-\u003eid, 'products/')); // true\n        }\n       \n    } finally {\n        $session-\u003eclose();    \n    }\n    \n} finally {\n    $store-\u003eclose();\n}\n```\n\n## Working with a secure server\n\nYour certificate and server certificate should be saved in PEM format to your machine.\n\n1.  Create AuthOptions:\n\n```php\n$authOptions = AuthOptions::pem(\n    '../clientCertPath.pem',\n    'clientCertPass',\n    '../serverCaCertPath.pem'\n);\n``` \n\n\n2. Pass auth options to `DocumentStore` object:\n\n```php\n$store = new DocumentStore('url', 'databaseName');\n$store-\u003esetAuthOptions($authOptions); // use auth options to connect on database\n$store-\u003einitialize();\n```\n\n## Running tests\n\nClone the repository:\n```bash\ngit clone https://github.com/ravendb/ravendb-php-client\n```\n\nInstall dependencies:\n```bash\ncomposer install\n```\nRun RavenDB server\n```bash\nhttps://a.phptest.development.run\n```\nSet environment variables.\n\n```bash\n# Set the following environment variables:\n#\n# - Certificate hostname\n# RAVENDB_PHP_TEST_HTTPS_SERVER_URL=https://a.phptest.development.run\n#\n# RAVENDB_PHP_TEST_CA_PATH=\n#\n# - Certificate path for tests requiring a secure server:\n# RAVENDB_PHP_TEST_CERTIFICATE_PATH=\n#\n# - Certificate for client\n# RAVENDB_TEST_CLIENT_CERT_PATH=\n# RAVENDB_TEST_CLIENT_CERT_PASSPHRASE=\n#\n# - For some tests, Developers licence is required in order to run them all \n# RAVEN_LICENSE=\n```\n\nRun PHPUnit\n```bash\n./vendor/bin/phpunit\n```\n\n-----\n##### Bug Tracker\n[http://issues.hibernatingrhinos.com/issues/RDBC](http://issues.hibernatingrhinos.com/issues/RDBC)\n\n-----\n##### License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fravendb%2Fravendb-php-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fravendb%2Fravendb-php-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fravendb%2Fravendb-php-client/lists"}