Skip to content
Reactions
Reactions
Universal reactions for MODX 3 — likes, GitHub-style sets, tops and trending on any object
  1. Extras
  2. Reactions
  3. Integrations
  4. miniShop3

miniShop3 integration

In snippets and the API pass the short class msProduct and the product ID (&object= / object_id). The server resolves the product via FQCN (MiniShop3\Model\msProduct) and STI modResource. It does not look up the short name in xPDO, so error.log stays clean.

Aggregates store object_class as msProduct (whatever you passed in class / class_key). Build catalog joins on that same string.

Reaction block on the product card

github in picker mode (chips + +):

modx
[[!Reactions?
    &class=`msProduct`
    &object=`[[*id]]`
    &set=`github`
    &context=`web`
]]
fenom
{'!Reactions' | snippet : [
    'class'   => 'msProduct',
    'object'  => $_modx->resource.id,
    'set'     => 'github',
    'context' => 'web',
]}

👍/👎 only:

modx
[[!Reactions?
    &class=`msProduct`
    &object=`[[*id]]`
    &set=`updown`
]]
fenom
{'!Reactions' | snippet : [
    'class'  => 'msProduct',
    'object' => $_modx->resource.id,
    'set'    => 'updown',
]}

Counter in the catalog

modx
[[!ReactionsCount?
    &class=`msProduct`
    &object=`[[+id]]`
    &format=`👍 {LIKES}`
]]
fenom
{'!ReactionsCount' | snippet : [
    'class'  => 'msProduct',
    'object' => $id,
    'format' => '👍 {LIKES}',
]}

Sort the catalog by popularity

Use msProducts with leftJoin.

modx
[[!msProducts?
    &parents=`10`
    &limit=`12`
    &leftJoin=`{"Aggregate":{"class":"Reactions\\Model\\ReactionAggregate","on":"Aggregate.object_id = msProduct.id AND Aggregate.object_class = 'msProduct'"}}`
    &sortby=`Aggregate.likes`
    &sortdir=`DESC`
    &tpl=`tpl.msProduct.card`
]]
fenom
{'!msProducts' | snippet : [
    'parents' => 10,
    'limit' => 12,
    'leftJoin' => '{"Aggregate":{"class":"Reactions\\Model\\ReactionAggregate","on":"Aggregate.object_id = msProduct.id AND Aggregate.object_class = \'msProduct\'"}}',
    'sortby' => 'Aggregate.likes',
    'sortdir' => 'DESC',
    'tpl' => 'tpl.msProduct.card',
]}

Top products

modx
[[!TopLiked?
    &class=`msProduct`
    &period=`month`
    &limit=`6`
    &tpl=`tpl.top.product`
]]
fenom
{'!TopLiked' | snippet : [
    'class'  => 'msProduct',
    'period' => 'month',
    'limit'  => 6,
    'tpl'    => 'tpl.top.product',
]}

Trending products:

modx
[[!Trending?
    &class=`msProduct`
    &limit=`8`
]]
fenom
{'!Trending' | snippet : [
    'class' => 'msProduct',
    'limit' => 8,
]}

Counter in the msProducts chunk

In tpl.msProduct.card:

modx
<div class="product-card">
    <h3>[[+pagetitle]]</h3>
    <p class="product-price">[[+price]] ₽</p>
    [[!ReactionsCount?
        &class=`msProduct`
        &object=`[[+id]]`
        &format=`❤️ {TOTAL}`
    ]]
</div>
fenom
<div class="product-card">
    <h3>{$pagetitle}</h3>
    <p class="product-price">{$price} ₽</p>
    {'!ReactionsCount' | snippet : [
        'class'  => 'msProduct',
        'object' => $id,
        'format' => '❤️ {TOTAL}',
    ]}
</div>

Context

Products usually live in the web context. If the catalog uses a separate context, pass context:

modx
[[!Reactions?
    &class=`msProduct`
    &object=`[[*id]]`
    &context=`catalog`
    &set=`updown`
]]
fenom
{'!Reactions' | snippet : [
    'class'   => 'msProduct',
    'object'  => $_modx->resource.id,
    'context' => 'catalog',
    'set'     => 'updown',
]}

JSON-LD on the product card

Only when the product has like/dislike votes. In Fenom use {raw …}:

modx
[[!ReactionsSchema?
    &class=`msProduct`
    &object=`[[*id]]`
    &context=`web`
]]
fenom
{raw ('!ReactionsSchema' | snippet : [
    'class'   => 'msProduct',
    'object'  => $_modx->resource.id,
    'context' => 'web',
])}

Recount aggregates

After a migration or import:

bash
php core/components/reactions/cli.php recount --class-key=msProduct