PHPackages                             get-stream/stream-doctrine - 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. get-stream/stream-doctrine

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

get-stream/stream-doctrine
==========================

Build newsfeeds and activity feeds with Doctrine using getstream.io

2.0.0(3y ago)64.0k3[1 PRs](https://github.com/GetStream/stream-doctrine/pulls)BSD-3-ClausePHPPHP &gt;=8.0

Since Nov 15Pushed 2y ago34 watchersCompare

[ Source](https://github.com/GetStream/stream-doctrine)[ Packagist](https://packagist.org/packages/get-stream/stream-doctrine)[ Docs](https://getstream.io/)[ RSS](/packages/get-stream-stream-doctrine/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (3)Dependencies (5)Versions (6)Used By (0)

Stream Doctrine
===============

[](#stream-doctrine)

[![Build Status](https://camo.githubusercontent.com/247fb60c22bb2940189b1f6839f9771750e20fd52640b707f9f12d075477b32b/68747470733a2f2f7472617669732d63692e6f72672f47657453747265616d2f73747265616d2d646f637472696e652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/GetStream/stream-doctrine)[![Code Coverage](https://camo.githubusercontent.com/e02b2070431ec85a862284c0c476de74ae7417576ec48f372ae9d8f700aac997/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f47657453747265616d2f73747265616d2d646f637472696e652f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/GetStream/stream-doctrine/)[![Code Quality](https://camo.githubusercontent.com/60351b049fec9b5c55c091f89b17643e4bd86ccd93353d8f58634d7894efb166/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f47657453747265616d2f73747265616d2d646f637472696e652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/GetStream/stream-doctrine/)[![Latest Stable Version](https://camo.githubusercontent.com/bd89a39e473d8f69eefd4a65a0cb4d11a03ca21fcf38141d8f50d65816e0e9d2/68747470733a2f2f706f7365722e707567782e6f72672f6765742d73747265616d2f73747265616d2d646f637472696e652f762f737461626c65)](https://packagist.org/packages/get-stream/stream-doctrine)[![License](https://camo.githubusercontent.com/54dd4e4260863353b8d5147347c16b208bb719fea34720724626bd326e785af1/68747470733a2f2f706f7365722e707567782e6f72672f6765742d73747265616d2f73747265616d2d646f637472696e652f6c6963656e7365)](https://packagist.org/packages/get-stream/stream-doctrine)

[stream-doctrine](https://github.com/GetStream/stream-doctrine) is a package that integrates you Doctrine entities with [Stream](https://getstream.io/).

You can sign up for a Stream account at [https://getstream.io/get\_started](https://getstream.io/get_started).

Note there is also a lower level [PHP - Stream integration](https://github.com/getstream/stream-php) library which is suitable for all PHP applications.

> 💡 This library is built for the **Feeds** product. The Chat product can be found [here](https://getstream.io/chat/docs/).

Build Activity Streams, News Feeds, and More
--------------------------------------------

[](#build-activity-streams-news-feeds-and-more)

[![](https://camo.githubusercontent.com/86b9b84c8e9abe92e94d6aad7cf60dd14516304714910497612a7c86fed89cf4/68747470733a2f2f6476716732646f6767676d6e362e636c6f756466726f6e742e6e65742f696d616765732f6d6f6f642d686f6d652e706e67)](https://camo.githubusercontent.com/86b9b84c8e9abe92e94d6aad7cf60dd14516304714910497612a7c86fed89cf4/68747470733a2f2f6476716732646f6767676d6e362e636c6f756466726f6e742e6e65742f696d616765732f6d6f6f642d686f6d652e706e67)

You can build:

- Activity Streams - like the one seen on GitHub
- A Twitter-like feed
- Instagram / Pinterest Photo Feeds
- Facebook-style newsfeeds
- A Notification System
- Lots more...

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

[](#installation)

### Composer

[](#composer)

```
composer require get-stream/stream-doctrine

```

Composer will install our latest version automatically.

### PHP compatibility

[](#php-compatibility)

Current releases require PHP `8.0` or higher, and depend on `doctrine/orm` version `2.14` or higher.

See the [GitHub build configuration](./.github/workflows) for details of how it is built and tested against different PHP versions.

GetStream.io Dashboard
----------------------

[](#getstreamio-dashboard)

Now, login to [GetStream.io](https://getstream.io) and create an application in the dashboard.

Retrieve the API key, API secret, and API app id, which are shown in your dashboard.

Stream-Doctrine setup
---------------------

[](#stream-doctrine-setup)

### Setup

[](#setup)

To register this plugin into Doctrine ORM, you need to register a `ModelListener` on the EntityManager like this:

```
$client = new GetStream\Stream\Client($apiKey, $apiSecret);

$manager = new GetStream\Doctrine\FeedManager($client);

$listener = new GetStream\Doctrine\ModelListener($manager);

$entityManager
    ->getConfiguration()
    ->getEntityListenerResolver()
    ->register($listener);
```

### Features of Stream-Doctrine

[](#features-of-stream-doctrine)

#### Entity integration

[](#entity-integration)

Stream-Doctrine provides instant integration with Doctrine entities - implementing the `GetStream\Doctrine\Activity` interface and adding an EntityListener will give you automatic tracking of your models to user feeds.

For example:

```
/**
 * @ORM\Table(name="pins")
 * @ORM\EntityListeners({"\GetStream\Doctrine\ModelListener"})
 */
class Pin implements Activity
{
    use ActivityTrait;
}
```

Every time a Pin is created it will be stored in the feed of the user that created it, and when a Pin instance is deleted then it will get removed as well.

Automatically!

### Activity Fields

[](#activity-fields)

Models are stored in feeds as activities. An activity is composed of at least the following data fields: **actor**, **verb**, **object**, **time**. You can also add more custom data if needed.

**object** is a reference to the entity instance itself **actor** is a reference to the user attribute of the instance **verb** is a string representation of the class name **time** is a DateTimeInterface object of when the activity happened. Mostly this will be the `created_at` or similar attribute of the entity.

A few assumptions are made on the entity class in order to be able to implement the ActivityInterface:

1. the Entity has an identifier (which goes for every entity).
2. the Entity has a \*-to-one relationship to some user or "actor".
3. the Entity has a timestamp column (`created_at` for example).

You can change how a entity instance is stored as activity by implementing specific methods as explained later.

An example of a complete Activity typed entity is shown below:

```
class Pin implements ActivityInterface
{
    use ActivityTrait;

    /**
     * Each pin is created by someone.
     *
     * @var User
     *
     * @ORM\ManyToOne(targetEntity="User", fetch="EXTRA_LAZY")
     * @ORM\JoinColumn(name="creator_id", referencedColumnName="id")
     */
    private $creator;

    /**
     * @ORM\Column(type="datetime_immutable", name="created_at")
     */
    private $createdAt;

    /**
     * @return string
     */
    public function activityVerb()
    {
        return 'pin';
    }

    /**
     * @return string
     */
    protected function activityId()
    {
        return $this->id;
    }

    /**
     * @return string
     */
    public function activityActorId()
    {
        return $this->creator->id();
    }

    /**
     * @return string
     */
    public function activityActor()
    {
        return User::class.':'.$this->activityActorId();
    }

    /**
     * @return DateTimeInterface
     */
    public function activityTime()
    {
        return $this->createdAt;
    }
```

You can change every `activity*` method according to your needs or entity implementation.

### Activity Extra Data

[](#activity-extra-data)

Often, you'll want to store more data than just the basic fields, for use with custom ranking or aggregation, for example. You achieve this by implementing the `activityExtraData` method in the entity.

NOTE: The data will be serialized using the json\_encode function, so it needs to be valid input for that.

```
class Tweet implements ActivityInterface
{
    use ActivityTrait;

    public function activityExtraData()
    {
        return ['is_retweet' => $this->isRetweet()];
    }
}
```

Feed Manager
------------

[](#feed-manager)

`stream-doctrine` comes with a FeedManager class (implementing FeedManagerInterface) that helps with all common feed operations. The FeedManager needs a configured `GetStream\Stream\Client` object when instantiating it.

Pre-Bundled Feeds
-----------------

[](#pre-bundled-feeds)

To get you started the manager has feeds pre configured. You can add more feeds if your application needs it. The three feeds are divided in three categories.

### User Feed:

[](#user-feed)

The user feed stores all activities for a user. Think of it as your personal Facebook page. You can easily get this feed from the manager.

```
/** @var $feed GetStream\Stream\Feed */
$feed = $feedManager->getUserFeed($userId);
```

### News Feed:

[](#news-feed)

The news feeds store the activities from the people you follow. You can setup the names of the newsfeeds using:

```
$feedManager->setNewsFeeds(['timeline', 'timeline_aggregated']);
```

Then you can access those feeds in an ArrayAccess kind of way:

```
$timelineFeed = $feedManager->getNewsFeed($userId)['timeline'];
$aggregatedTimelineFeed = FeedManager::getNewsFeed($userId)['timeline_aggregated'];
```

Both user feed and news feeds are shorthand methods for:

```
$feed = $feedManager->getFeed('user', $userId);
$feed = $feedManager->getFeed('timeline', $userId);
$feed = $feedManager->getFeed('timeline_aggregated', $userId);
```

### Notification Feed:

[](#notification-feed)

The notification feed can be used to build notification functionality.

[![Notification feed](https://camo.githubusercontent.com/f759c55bdb0c06e835e3401ce4611d3b49d0695bd216ca949c2b99b80e81c16c/687474703a2f2f666565646c792e72656164746865646f63732e6f72672f656e2f6c61746573742f5f696d616765732f66625f6e6f74696669636174696f6e5f73797374656d2e706e67)](https://camo.githubusercontent.com/f759c55bdb0c06e835e3401ce4611d3b49d0695bd216ca949c2b99b80e81c16c/687474703a2f2f666565646c792e72656164746865646f63732e6f72672f656e2f6c61746573742f5f696d616765732f66625f6e6f74696669636174696f6e5f73797374656d2e706e67)

Below we show an example of how you can read the notification feed.

```
$notificationFeed = $feedManager->getNotificationFeed($user->id);
```

By default the notification feed will be empty. You can specify which users to notify when your model gets created. In the case of a retweet you probably want to notify the user of the parent tweet.

```
class Tweet implements ActivityInterface
{
    use ActivityTrait;

    /**
     * @return array
     */
    public function activityNotify()
    {
        if ($this->isRetweet()) {
            return ['notification:'.$this->parent()->user()->id()];
        }

        return [];
    }
```

Another example would be following a user. You would commonly want to notify the user which is being followed.

```
class Follow implements ActivityInterface
{
    use ActivityTrait;

    /**
     * @return array
     */
    public function activityNotify()
    {
        return ['notification:'.$this->target()->id()];
    }
}
```

Follow Feed
-----------

[](#follow-feed)

To create the news feeds you need to notify the system about follow relationships. The manager comes with methods to let a user's news feeds follow another user's feed. This code lets the current user's news feeds follow the target\_user's personal feed.

```
/** @var GetStream\Doctrine\FeedManager $manager */
$manager->setNewsFeeds(['timeline', 'timeline_aggregated']);
$manager->followUser($userId, $targetId);

// Same as:
$targetFeed = $client->feed('user', $targetId);
$feed1 = $client->feed('timeline', $userId);
$feed2 = $client->feed('timeline_aggregated', $userId);

$feed1->follow($targetFeed->getSlug(), $targetFeed->getId());
$feed2->follow($targetFeed->getSlug(), $targetFeed->getId());

```

Displaying the Newsfeed
-----------------------

[](#displaying-the-newsfeed)

### Activity Enrichment

[](#activity-enrichment)

When you read data from feeds with activities created by `stream-doctrine`, an activity will look like this:

```
{
    "actor": "User:1",
    "verb": "like",
    "object": "Like:42"
}
```

This is far from ready for usage in your template. We call the process of loading references from the database: enrichment. An example is shown below.

```
use GetStream\Doctrine\Enrich;

$feed = $feedManager->getUserFeed($userId);
$activities = $feed->getActivities(0, 25)['results'];

$enricher = new Enrich();
$activities = $enricher->enrichActivities($activities);
```

### Customizing Enrichment

[](#customizing-enrichment)

Sometimes you'll want to customize how enrichment works. If you store references to model instances as custom fields (using the `activityExtraData()` method) you can use the `Enrich` class to take care of it for you:

```
class Pin implements ActivityInterface
{
    use ActivityTrait;

    public function activityExtraData()
    {
        return ['parent_tweet' => self::class.':'.$this->parent()->id()];
    }
}
```

Tell the enricher to enrich the `parent_tweet` field into a full entity object:

```
$enricher = (new Enrich()->setEnrichingFields(['actor', 'object', 'parent_tweet']));
$activities = $feed->getActivities(0,25)['results'];
$activities = $enricher->enrichActivities($activities);
```

### Full documentation and Low level APIs access

[](#full-documentation-and-low-level-apis-access)

When needed you can also use the [low level PHP API](https://github.com/getstream/stream-php) directly. Documentation is available at the [Stream website](https://getstream.io/docs/?language=php).

```
/** @var $client GetStream\Stream\Client */
$client = $feedManager->getClient();

```

### Copyright and License Information

[](#copyright-and-license-information)

Copyright (c) 2014-2022 Stream.io Inc, and individual contributors. All rights reserved.

See the file "LICENSE" for information on the history of this software, terms &amp; conditions for usage, and a DISCLAIMER OF ALL WARRANTIES.

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity24

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 66.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 ~963 days

Total

3

Last Release

1177d ago

Major Versions

1.0.0-alpha.1 → 2.0.02023-02-23

### Community

Maintainers

![](https://www.gravatar.com/avatar/ce219558b7b17254ff0ab7a17e7167d4b52df7353e5bfd8dad1edb8924684b8e?d=identicon)[tbarbugli](/maintainers/tbarbugli)

---

Top Contributors

[![hannesvdvreken](https://avatars.githubusercontent.com/u/1410358?v=4)](https://github.com/hannesvdvreken "hannesvdvreken (18 commits)")[![tbarbugli](https://avatars.githubusercontent.com/u/88735?v=4)](https://github.com/tbarbugli "tbarbugli (4 commits)")[![JimmyPettersson85](https://avatars.githubusercontent.com/u/953852?v=4)](https://github.com/JimmyPettersson85 "JimmyPettersson85 (2 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")[![marco-ulge](https://avatars.githubusercontent.com/u/54494803?v=4)](https://github.com/marco-ulge "marco-ulge (1 commits)")[![peterdeme](https://avatars.githubusercontent.com/u/19969687?v=4)](https://github.com/peterdeme "peterdeme (1 commits)")

---

Tags

activity-feeddoctinefeedgetstream-ionews-feednotification-feedormstream-doctrinestream-phptimelinestreamsymfonyfeedormdoctrineactivityfeedlynewsfeedgetstreamactivity feednotification feedaggregated feed

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/get-stream-stream-doctrine/health.svg)

```
[![Health](https://phpackages.com/badges/get-stream-stream-doctrine/health.svg)](https://phpackages.com/packages/get-stream-stream-doctrine)
```

###  Alternatives

[get-stream/stream-laravel

Build newsfeeds and activity feeds on Laravel using getstream.io

328327.1k](/packages/get-stream-stream-laravel)[sonata-project/doctrine-orm-admin-bundle

Integrate Doctrine ORM into the SonataAdminBundle

46117.7M155](/packages/sonata-project-doctrine-orm-admin-bundle)[omines/datatables-bundle

Symfony DataTables Bundle with native Doctrine ORM, Elastica and MongoDB support

2851.4M6](/packages/omines-datatables-bundle)[goodwix/doctrine-json-odm

JSON Object-Document Mapping bundle for Symfony and Doctrine

2226.0k](/packages/goodwix-doctrine-json-odm)

PHPackages © 2026

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