PHPackages                             gdbots/ncr - 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. gdbots/ncr

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

gdbots/ncr
==========

Node Content Repository for php.

v3.1.2(1y ago)122.6k↓33.3%114Apache-2.0PHPPHP &gt;=8.1

Since Mar 27Pushed 1y ago7 watchersCompare

[ Source](https://github.com/gdbots/ncr-php)[ Packagist](https://packagist.org/packages/gdbots/ncr)[ RSS](/packages/gdbots-ncr/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (74)Used By (14)

ncr-php
=======

[](#ncr-php)

Node Content Repository for php. Using this library assumes that you've already created and compiled your own pbj classes using the [Pbjc](https://github.com/gdbots/pbjc-php) and are making use of the **"gdbots:ncr:mixin:\*"** mixins from [gdbots/schemas](https://github.com/gdbots/schemas).

> If your project is using Symfony use the [gdbots/ncr-bundle-php](https://github.com/gdbots/ncr-bundle-php) to simplify the integration.

Nodes and Edges
===============

[](#nodes-and-edges)

A [node or vertex](https://en.wikipedia.org/wiki/Graph_theory) is a *noun/entity* in your system. An article, tweet, video, person, place, order, product, etc. The edges are the *relationships* between those things like "friends", "tagged to", "married to", "published by", etc.

This library doesn't provide you with a graph database implementation. It's concerned with persisting/retrieving nodes and edges. Graph traversal would still need to be provided by another library. It is recommended that data be replicated or projected out of the Ncr (or layered on top like [GraphQL](http://graphql.org/)) into something suited for that purpose (e.g. Neo4j, Titan ElasticSearch).

NodeRef
=======

[](#noderef)

A NodeRef is a qualified identifier to a node/vertex. It is less verbose than a `MessageRef` as it is implied that node labels must be unique within a given vendor namespace and therefore can be represented in a more compact manner.

> **NodeRef Format:** vendor:label:id The **"vendor:label"** portion is a `SchemaQName`

**Examples:**

> acme:article:41e4532f-2f58-4b9d-afc8-e9c2cbcb4aba twitter:tweet:789234931599835136 youtube:video:EG0wQRsXLi4

Nodes do not actually have a `node_ref` field, they have an `_id` field. The `NodeRef` is derived by taking the `SchemaQName` of the node's schema along with its `_id`. The `NodeRef` is an immutable value object which is used in various places without needing to actually have the node instance.

Ncr
===

[](#ncr)

The Ncr is the service responsible for node persistence. It is intentionally limited to basic key/value storage operations (e.g. put/get/find by index) to ensure the underlying implementation can be swapped out with little effort or decorated easily (caching layers for example).

**Available repository implementations:**

- DynamoDb
- Psr6 *(gives you Redis, File, Memcached, Doctrine, etc.)*
- InMemory

Review the `Gdbots\Ncr\Ncr` interface for reference on the available methods.

Ncr::findNodeRefs
-----------------

[](#ncrfindnoderefs)

The Ncr is a simple key/value store which means querying is limited to the id of the item or a secondary index. An example of a secondary index would be the email or username of a user, the slug of an article or the isbn of a book.

An `IndexQuery` is used to `findNodeRefs` that match a query against a secondary index.

**An example of using a IndexQuery:**

```
$query = IndexQueryBuilder::create(SchemaQName::fromString('acme:user'), 'email', 'homer@simpson.com')
    ->setCount(1)
    ->build();
$result = $this->ncr->findNodeRefs($query);
if (!$result->count()) {
    throw new NodeNotFound('Unable to find homer.');
}

$node = $this->ncr->getNode($result->getNodeRefs()[0]);
```

Not all storage engines can enforce uniqueness on a secondary index so the interface also cannot make that assumption. Because of this the `findNodeRefs` may return more than one value. It is up to your application logic to deal with that.

Ncr::pipeNodes
--------------

[](#ncrpipenodes)

Getting data out of the Ncr should be dead simple, it's just json after all. Use the `pipeNodes` or `pipeNodeRefs` methods to export data. The **gdbots/ncr-bundle-php** provides console commands that make use of this to export and reindex nodes.

**Exporting nodes using pipeNodes:**

```
foreach ($ncr->pipeNodes(SchemaQName::fromString('acme:article')) as $node) {
    echo json_encode($node) . PHP_EOL;
}
```

NcrCache
========

[](#ncrcache)

NcrCache is a first level cache which is ONLY seen and used by the current request. It is used to cache all nodes returned from get node request(s). This cache is used during [Pbjx](https://github.com/gdbots/pbjx-php) request processing or if the Ncr is running in the current process and is using the MemoizingNcr.

> This cache should not be used when asking for a consistent result.

**NcrCache is NOT an identity map** and the **Ncr is NOT an ORM**. In some cases you may get the same exact object but it's not a guarantee so don't do something like this:

```
$nodeRef = NodeRef::fromString('acme:article:123');
$cache->getNode($nodeRef) !== $cache->getNode($nodeRef);
```

If you need to check equality, use the message interface:

```
$node1 = $cache->getNode($nodeRef);
$node2 = $cache->getNode($nodeRef);
$node->equals($node2); // returns true if their data is the same
```

NcrLazyLoader
=============

[](#ncrlazyloader)

NcrCache and other request interceptors make use of this service to batch load nodes only if they are requested. An example of this is when loading an article you may want to fetch the author or related items, but not always. Rather than force the logic to exist in the loading of an article, something else can manage that.

> Lazy loading is generally application specific so this library provides some tools to make is easier.

**Example lazy loading:**

```
public function onSearchNodesResponse(ResponseCreatedEvent $pbjxEvent): void
{
    $response = $pbjxEvent->getResponse();
    if (!$response->has('nodes')) {
        return;
    }

    // for all nodes in this search response, mark the creator
    // and updater for lazy load.  if they get requested at some point
    // in the current request, it will be batched for optimal performance
    $this->lazyLoader->addEmbeddedNodeRefs($response->get('nodes'), [
        'creator_ref' => 'acme:user',
        'updater_ref' => 'acme:user',
    ]);
}
```

NcrSearch
=========

[](#ncrsearch)

The Ncr provides the reliable storage and retrieval of Nodes. NcrSearch is in most cases a separate storage provider. For example, DynamoDb for Ncr and ElasticSearch for NcrSearch. In fact, the only implementation we have right now is ElasticSearch.

When using the **gdbots/ncr-bundle-php** you can enable the indexing with a simple configuration option. The bundle also provides a reindex console command.

Searching nodes is generally done in a request handler. Here is an example of searching nodes:

```
public function handleRequest(Message $request, Pbjx $pbjx): Message
{
    $parsedQuery = ParsedQuery::fromArray(json_decode($request->get('parsed_query_json', '{}'), true));

    $response = SearchUsersResponseV1::create();
    $this->ncrSearch->searchNodes(
        $request,
        $parsedQuery,
        $response,
        [SchemaQName::fromString('acme:user')]
    );

    return $response;
}
```

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance31

Infrequent updates — may be unmaintained

Popularity28

Limited adoption so far

Community26

Small or concentrated contributor base

Maturity87

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 87.7% 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 ~37 days

Recently: every ~224 days

Total

72

Last Release

718d ago

Major Versions

v0.3.26 → v1.0.02019-06-09

v1.0.12 → v2.0.02020-06-28

v1.0.15 → v2.1.22020-10-01

v1.0.16 → v2.1.42021-03-17

v2.1.7 → v3.0.02021-12-10

PHP version history (3 changes)v0.1.0PHP &gt;=7.1

v2.0.0PHP &gt;=7.4

v3.0.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/04ecf55609310eefdd08182fdc75aec01f6c5aa9657ec6729ac54e6f5dd5f0ef?d=identicon)[gdbrown](/maintainers/gdbrown)

---

Top Contributors

[![gdbrown](https://avatars.githubusercontent.com/u/3344831?v=4)](https://github.com/gdbrown "gdbrown (64 commits)")[![mynameisgabe](https://avatars.githubusercontent.com/u/535771?v=4)](https://github.com/mynameisgabe "mynameisgabe (3 commits)")[![efjacobson](https://avatars.githubusercontent.com/u/6315388?v=4)](https://github.com/efjacobson "efjacobson (2 commits)")[![hunyoboy](https://avatars.githubusercontent.com/u/4349457?v=4)](https://github.com/hunyoboy "hunyoboy (2 commits)")[![bhsiao55](https://avatars.githubusercontent.com/u/7938495?v=4)](https://github.com/bhsiao55 "bhsiao55 (1 commits)")[![weiwang314](https://avatars.githubusercontent.com/u/15330153?v=4)](https://github.com/weiwang314 "weiwang314 (1 commits)")

---

Tags

ncrpbjpbjx

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/gdbots-ncr/health.svg)

```
[![Health](https://phpackages.com/badges/gdbots-ncr/health.svg)](https://phpackages.com/packages/gdbots-ncr)
```

###  Alternatives

[doctrine/dbal

Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.

9.7k578.4M5.6k](/packages/doctrine-dbal)[kreait/firebase-php

Firebase Admin SDK

2.4k39.7M72](/packages/kreait-firebase-php)[api-platform/metadata

API Resource-oriented metadata attributes and factories

243.5M96](/packages/api-platform-metadata)[nettrine/orm

Doctrine ORM for Nette Framework

581.9M37](/packages/nettrine-orm)[tommyknocker/pdo-database-class

Framework-agnostic PHP database library with unified API for MySQL, MariaDB, PostgreSQL, SQLite, MSSQL, and Oracle. Query Builder, caching, sharding, window functions, CTEs, JSON, migrations, ActiveRecord, CLI tools, AI-powered analysis. Zero external dependencies.

845.7k](/packages/tommyknocker-pdo-database-class)[perplorm/perpl

Perpl is an improved and still maintained fork of Propel2, an open-source Object-Relational Mapping (ORM) for PHP.

203.7k](/packages/perplorm-perpl)

PHPackages © 2026

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