Софтуерно Инженерство
Loading...
perer avatar perer 0 Точки

Обект от тип PHP Generator в JSON

Здравейте, коелги!

Правя проект, в който използвам PHP Generator, за да извлека данните от базата. Тъй като за визуализацията им трябва доста солидна обработка и реших, че най-добре би било, ако направя генерирания обект в JSON стринг, който след това да обработя с JS. Тук идва и проблемът. Какво ли не опитах и не става. Винаги ми връща или празен стринг "{}", или null.

Някой има ли опит с това и има ли начин да се направи въобще?

Благодаря и поздрави!

Тагове:
0
PHP Web
RoYaL avatar RoYaL SoftUni Team Trainer 6795 Точки

Здравей,

Използването на генератори на данни, които спомагат максималното забавяне на истинската работа с данните е супер идея в смисъла на оптимизация. Но, единственият начин да създадеш низ (в случая под формата на JSON) с тази поредица от данни е да генерираш тази поредица от данни. Та щом си стигнал този момент, вече е време да превърнеш генератора в данни.

Възможен начин е да превърнеш поредицата в масив, чрез вградената функция iterator_to_array(). След което да кодираш този масив в JSON използвайки вградената json_encode() функция. Проблемът на този подход е, че първата функция ще мине през всички данни веднъж и ще ги запише в паметта като масив, втората ще мине през тях отново (под формата на масив) и ще ги запише в паметта като низ. Двойна обработка на едни и същи данни.

За съжаление не се сещам да има вграден вариант да превърнеш неоценена поредица направо в JSON низ. Затова ще се наложи да го направиш ръчно - обхождайки генераторът и създавайки низ на момента. Няколко предложения за такива функции има в тема, в която се пита същия въпрос като твоя. Може би е хубаво да пробваш да търсиш решения на проблемите си в интернет - през 2017та хората вероятно са се сблъскали с твоя проблем преди :).

Успех!

0
perer avatar perer 0 Точки

Разбира се, че потърсих в нета преди да пиша тук, но явно не правя нещата както трябва и не ми се получава :)

Така, структурата ми е следната:

Имам сървиси, които се теглят информацията от базата и я пращат на генератора:

//заявката към базата...
$expenseByOffice = new ExpenseStockViewData();

$expenseByOffice->setExpense(
            function () use ($expenseStmt){
                while ($expense = $expenseStmt->fetchObject(ExpenseForStock::class)){
                    yield $expense;
                }
            }
        );

//return...

В този ExpenseStockViewData клас пък има следното:
 

class ExpenseStockViewData
{
    private $expense;

    public function getExpense()
    {
        return $this->expense;
    }

    /**
     * @param callable $expense
     */
    public function setExpense(callable $expense)
    {
        $this->expense = $expense();
    }
}

Изтрих анотациите над пропъртито и getter-а, защото си мислех, че те са проблем, но уви не са.

Така обработената информация се вика от файл и се праща към темплейта:

$service = new StockService($db);
$templateData = $service->stockByOffice(param);

$app->loadTemplate('stock_frontend', $templateData);

В темплейта вече взимам променливата, "тегля" данните от генератора през getter-а му и обработвам данните като масив.

Къде ли не слагах функцията от stackoverflow, открих и нещо за JsonSerializable интерфейса и неговата функция jsonSerialize(), но явно не я слагам на правилното място, защото ефектът е същия.

Това, което опитах вече е:

  • Класът ExpenseForStock да имплементира интерфейса JsonSerializable и функцията jsonSerialize() да връща всичките му пропъртита в масив. След това в темплейта викам json_encode() и ефекта е "{}".
  • Функцията от темата, която ми даде използах леко преработена (открих я в друга подобна тема) и я виках в setter-а на класа ExpenseStockViewData:
/**
     * @param callable $expense
     */
    public function setExpenseJSON(callable $expense)
    {
        $this->expense = $this->json_encode_objs($expense());
    }

    function json_encode_objs($item)
    {
        if(!is_array($item) && !is_object($item)){
            return json_encode($item);
        }else{
            $pieces = array();
            foreach($item as $k=>$v){
                $pieces[] = "\"$k\":" . $this->json_encode_objs($v);
            }
            return '{'.implode(',',$pieces).'}';
        }
    }

Тук имаше лек напредък. Резултатът бе -

  string(39) "{"0":{"userID":"2"},"1":{"userID":"2"}}"
В базата имам два записа, направени от един си същи потребител.

 

Таа, да, не мога да открия къде греша и защо не става. Много благодаря за помощта!

0
30/06/2017 16:36:49