Loading...
perer avatar perer 0 Точки

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

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

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

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

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

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

Здравей,

Използването на генератори на данни, които спомагат максималното забавяне на истинската работа с данните е супер идея в смисъла на оптимизация. Но, единственият начин да създадеш низ (в случая под формата на 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
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.