Laravel уменьшить количество знаков после запятой

У меня есть конечная точка API, которая указывает на /api/invoices и возвращает список счетов.

Некоторые счета-фактуры возвращают что-то вроде этого:

{
    "id": 2555,
    "entity_id": 88,
    "net_total": 7.5,
    "total_vat": 1.725000000000000088817841970012523233890533447265625,
    "grand_total": 9.2249999999999996447286321199499070644378662109375,
}

Как видите, слишком много знаков после запятой. Все мои денежные столбцы обозначены как double(20,5), потому что программное обеспечение должно обрабатывать до 5 знаков после запятой (но в основном только 2) и 20 единиц.

Есть ли способ заставить через MySQL или Laravel всегда возвращать 5 знаков после запятой? Я не могу использовать:

->selectRaw('ROUND(total_vat, 5) as total_vat')

Потому что у меня около 100 столбцов, и я получаю их все без использования ->select().

Что происходит, когда вы используете DECIMAL вместо DOUBLE?

Bill Karwin 05.02.2023 01:59

@BillKarwin хм, хорошее предложение. Я реализовал, и в результате получается только 5 знаков после запятой, но у меня есть два вопроса: 1. Мое программное обеспечение находится в производстве, и у меня более 200 тыс. строк, есть ли проблема при переходе с DOUBLE на DECIMAL? 2. Вывод в Laravel/Postman отображается как строка (с двойными кавычками) «1.72500» вместо числа, это нормально?

Linesofcode 05.02.2023 02:11

Вы можете определить масштаб DECIMAL. Я обычно использую DECIMAL(9,2) для валюты. В некоторых финансовых приложениях стандартно используется 4-разрядная шкала, так что это будет DECIMAL(11,4). Вы должны тщательно протестировать — а не на своих производственных данных — чтобы убедиться, что преобразование происходит так, как вы ожидаете. Не верьте тому, что говорит какой-то незнакомец в Интернете, и сначала сделайте резервную копию своих данных.

Bill Karwin 05.02.2023 02:17

Вам также следует прочитать dev.mysql.com/doc/refman/en/problems-with-float.html и docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html. Судя по вашему профилю, вы уже много лет работаете программистом. Эта информация не должна быть для вас новой.

Bill Karwin 05.02.2023 02:19

Если вы планируете изменить тип столбца, вы также можете рассмотреть возможность сохранения значения цента в столбце типа int. И, честно говоря, это может избавить вас от многих головных болей, с которыми вы сталкиваетесь прямо сейчас, и это один из способов решения дилеммы с плавающей запятой.

user3532758 05.02.2023 02:26

@BillKarwin Я только что видел это stackoverflow.com/a/24135191/3355243, где парень говорит, что если столбец соответствует тем же данным (20,5), то преобразование из double в decimal должно быть нормальным.

Linesofcode 05.02.2023 02:52

@ user3532758 не может сделать это прямо сейчас. Проект большой, уже в продакшене, и у меня много валютных колонок. Было бы затруднительно создать столбец центов для каждого.

Linesofcode 05.02.2023 02:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
7
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Решение состоит в том, чтобы преобразовать столбцы в десятичные числа и сохранить ту же структуру, как сказано в этом сообщении https://stackoverflow.com/a/24135191/3355243.

Я сделал несколько тестов, и значение столбца сохранило исходные данные.

Однако это приведет к другой проблеме, которая заключается в том, что laravel использует десятичное число как строку. Используя postman, мы видим, что значения валюты приходят в виде строки, например «15.00». Чтобы решить эту проблему, мы можем использовать cast Eloquent приведения десятичного числа к строке:

protected $casts = 
[
    'net_total' => 'float',
];

Мне не удалось найти/проверить, создает ли использование приведения какие-либо проблемы с исходным значением.

Будьте осторожны при преобразовании DOUBLE в DECIMAL, так как, как и в моем случае, это может вызвать серьезные проблемы в вашем проекте. Например, мое мобильное приложение перестало работать после конвертации, потому что не готово обрабатывать значения валюты как строку.

Я бы предложил использовать ресурсы API для преобразования данных.

Если вы просто вернете Invoices::all() в своем API, то да, он вернет «как есть».

Но типичным способом преобразования любых данных будет Ресурсы API:

php artisan make:resource InvoiceResource

Затем внутри этого ресурса вы возвращаете только то, что вам нужно, и преобразуете, как хотите, включая 5 цифр:

приложение/Http/Ресурсы/InvoiceResource.php:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'entity_id' => $this->entity_id,
        'net_total' => $this->net_total,
        'total_vat' => number_format($this->total_vat, 5),
        'grand_total' => number_format($this->grand_total, 5),
    ];
}

Затем в контроллере:

public function index() {
    return InvoiceResource::collection(Invoice::all());
}

Кроме того, ресурсы API будут добавлять слой-оболочку «данные» по умолчанию при возврате, поэтому вы можете избежать этого, а затем добавить это в AppServiceProvider:

приложение/Провайдеры/AppServiceProvider.php:

use Illuminate\Http\Resources\Json\JsonResource;
 
class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        JsonResource::withoutWrapping();
    }
}

Привет, я знаю о ресурсе API и использую его в последних проектах, но в этом конкретном проекте я не могу по нескольким причинам. Палец вверх за решение.

Linesofcode 05.02.2023 16:02

Другие вопросы по теме