PHPackages                             lyrasoft/token-coin - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. lyrasoft/token-coin

ActiveWindwalker-package[Utility &amp; Helpers](/categories/utility)

lyrasoft/token-coin
===================

LYRASOFT Token Coin Package

0.1.1(1y ago)0341[2 issues](https://github.com/lyrasoft/token-coin/issues)MITPHP

Since Apr 25Pushed 1y ago1 watchersCompare

[ Source](https://github.com/lyrasoft/token-coin)[ Packagist](https://packagist.org/packages/lyrasoft/token-coin)[ RSS](/packages/lyrasoft-token-coin/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (3)Used By (0)

LYRASOFT Token Coins Package
============================

[](#lyrasoft-token-coins-package)

[![Image](https://private-user-images.githubusercontent.com/1639206/437330272-f2da7373-8a4c-4b68-8c2d-24b3974ecdfd.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzUwMDg4NTMsIm5iZiI6MTc3NTAwODU1MywicGF0aCI6Ii8xNjM5MjA2LzQzNzMzMDI3Mi1mMmRhNzM3My04YTRjLTRiNjgtOGMyZC0yNGIzOTc0ZWNkZmQuanBnP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDQwMSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjA0MDFUMDE1NTUzWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9Yjg5OTI3MDY0Yjg0ODI2YTZlOGM1ZGRhMmVkNTU1NjA4YTgzYjU5OTEyNDk4YmVjY2RiZDRlMzg0OGQzZDE4YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.36Bg9ogjyyOQ8PJ-XuZZAQqCp0mbG0aGP7OsBJ81qRk)](https://private-user-images.githubusercontent.com/1639206/437330272-f2da7373-8a4c-4b68-8c2d-24b3974ecdfd.jpg?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzUwMDg4NTMsIm5iZiI6MTc3NTAwODU1MywicGF0aCI6Ii8xNjM5MjA2LzQzNzMzMDI3Mi1mMmRhNzM3My04YTRjLTRiNjgtOGMyZC0yNGIzOTc0ZWNkZmQuanBnP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDQwMSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjA0MDFUMDE1NTUzWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9Yjg5OTI3MDY0Yjg0ODI2YTZlOGM1ZGRhMmVkNTU1NjA4YTgzYjU5OTEyNDk4YmVjY2RiZDRlMzg0OGQzZDE4YyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.36Bg9ogjyyOQ8PJ-XuZZAQqCp0mbG0aGP7OsBJ81qRk)

- [LYRASOFT Token Coins Package](#lyrasoft-token-coins-package)
    - [Installation](#installation)
        - [Menu](#menu)
    - [Usages](#usages)
        - [Available Actions](#available-actions)
        - [Type](#type)
        - [Check Available](#check-available)
    - [Callbacks](#callbacks)
        - [Inline Callback](#inline-callback)
        - [Global Callback](#global-callback)
    - [UI](#ui)

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

[](#installation)

Install from composer

```
composer require lyrasoft/token-coin
```

Then copy files to project

```
php windwalker pkg:install lyrasoft/token-coin -t routes -t migrations
```

### Menu

[](#menu)

Add this to `sidemenu.menu.php`

```
// Token Coins
$menu->link('點數歷史')
    ->to($nav->to('token_coin_history_list'))
    ->icon('fa-light fa-ticket');
```

Usages
------

[](#usages)

You can pre-add a column to record the remaining token coins in your user table.

```
    $mig->createTable(
        User::class,
        function (Schema $schema) {
            // ...
            $schema->decimal('token_coins')->length('20,4');

            // ...

            $schema->addIndex('token_coins');

            // ...
        }
    );

    // OR

    $mig->updateTable(
        User::class,
        function (Schema $schema) {
            $schema->decimal('token_coins')->length('20,4')->after('password');
            $schema->addIndex('token_coins');
        }
    );
```

Then add token coins by the following code, you may add this code in seeders.

```
use \Lyrasoft\TokenCoin\Enum\TokenCoinAction;

foreach ($userIds as $userId) {
    /** @var \Lyrasoft\TokenCoin\Service\TokenCoinService $tokenCoinService */
    $tokenCoinService->modifyAndAddHistory(
        type: 'main',
        targetId: $userId,
        action: TokenCoinAction::PLUS,
        value: 500,
        // You can modify TokenCoinHistory entity here
        beforeSave: function (TokenCoinHistory $history) use ($currentUser, $tokenCoinData) {
            $history->setNote($tokenCoinData['note']); // The note messgage
            $history->setAgentId($currentUser->getId()); // Who did this action
        },
        // Udpdate remaining values
        updateRemain: function (float $remain, mixed $targetId, string|\BackedEnum $type) use ($orm, $currentUser) {
            $orm->updateBatch(
                User::class,
                [
                    'token_coins' => $remain,
                ],
                ['id' => $targetId]
            );
        }
    );
}
```

### Available Actions

[](#available-actions)

```
/** @var \Lyrasoft\TokenCoin\Service\TokenCoinService $tokenCoinService */

// plus/reduce/use actions
$tokenCoinService->plus($type, 500, $targetId, ...);
$tokenCoinService->reduce($type, 500, $targetId, ...);
$tokenCoinService->use($type, 500, $targetId, ...);

$tokenCoinService->modifyAndAddHistory($type, $action, $value, $targetId, ...);

// Other utilities

// Is enough to use/reduce
$tokenCoinService->isEnoughToReduce($type, $targetId, 500); // (bool)

// Is the remain larger than 0
$tokenCoinService->hasBalance($type, $targetId); // (bool)

// Get remaining value
$tokenCoinService->getRemain($type, $targetId); // (float)

// Get laat history entity
$tokenCoinService->getLastHistory($type, $targetId, sortBy: 'id'); // ?TokenCoinHistory

// Sum the total usage of a month of given time.
$tokenCoinService->getUsageTotalByMonth($type, $targetId, current: 'now'); // (float)

// Sum the total usage between two dates
$tokenCoinService->getUsageTotalBetween($type, $targetId, $start, $end); // (float)
```

### Type

[](#type)

You can use string or custom enum as type:

```
$tokenCoinService->modifyAndAddHistory('reward');
$tokenCoinService->modifyAndAddHistory(MyTokenCoinType::REWARD);
```

### Check Available

[](#check-available)

If you are not allowing the overdraw, you can check the available token coins before using it.

```
/** @var \Lyrasoft\TokenCoin\Service\TokenCoinService $tokenCoinService */
$orm->transaction(
    function () use ($tokenCoinService, $orm, $userId) {
        $type = MyTokenCoinType::REWARD;
        $useValue = 699;

        // Check if the user has enough token coins
        if ($tokenCoinService->isEnoughToReduce($type, $userId, $useValue)) {
            $tokenCoinService->use($type, $useValue, $userId);
        } else {
            // Not enough token coins
            throw new \RuntimeException('Not enough token coins.', 403);
        }
    }
);
```

If you didn't check first, it may be reduce to negative value

```
$history = $tokenCoinService->use($type, $useValue, $userId);

// $history->getRemain() < 0
```

If you allows the overdraw, but must larger than 0, you can check the balance:

```
/** @var \Lyrasoft\TokenCoin\Service\TokenCoinService $tokenCoinService */
$orm->transaction(
    function () use ($tokenCoinService, $orm, $userId) {
        $type = MyTokenCoinType::REWARD;
        $useValue = 699;

        // Check if the user has enough token coins
        if ($tokenCoinService->hasBalance($type, $userId)) {
            $tokenCoinService->use($type, $useValue, $userId);
        }
    }
);
```

Callbacks
---------

[](#callbacks)

There are 2 callbacks you can use, `beforeSave` is to modify the history entity before saving, and `updateRemain` is to update the remaining value:

### Inline Callback

[](#inline-callback)

Use the callbacks inline ehen you modify coins:

```
$tokenCoinService->plus(
    ...
    beforeSave: function (TokenCoinHistory $history) {
        // ...
    },
    updateRemain: function (float $remain, mixed $targetId, string|\BackedEnum $type) {
        // ...
    }
);
```

The callbacks is execute by `Container` so you can resort the arguments' ordering, And you can also inject services in the callbacks:

```
function (string|\BackedEnum $type, \Windwalker\ORM\ORM $orm, float $remain, mixed $targetId) {
    // ...
}
```

### Global Callback

[](#global-callback)

You can set the default callbacks in the `config` file:

```
