thmsnhl

Clean way to output data as json

Recommended Posts

Hi everyone,

I've recently hired at a new company and here I am evaluating the abilities of ProcessWire for our projects.
I was able to meet almost every requirement so far, but there is one point I couldn't find an adequate solution for: outputting data to json.

I am aware of modules like https://modules.processwire.com/modules/pages2-json/ (which does not seem to work for me) but I thought with a function like wireEncodeJSON this should be much cleaner. What I would like to achieve is outputting pages with according field values into an array to use this within javascript.
My first attempt on this was:

$jsontestOne = $pages->find(1001)->children();
echo wireEncodeJSON($jsontestOne);

which outputs 

[{}]

and afterwards I tried that one:

$jsontest = $pages->find("template=basic-page")->getArray();
echo wireEncodeJSON($jsontest);

which outputs 

[{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},...]

Maybe you can point out where my mistake is.
 

Thanks in advance!

Share this post


Link to post
Share on other sites

Hi @thmsnhl

Have you seen this thread? 

There is an example that you may find useful

$events = $pages->find("template=sectionItem, parent=1025|1066|1073|1069|1013|1247|1101, sort=startTime, start=10, limit=3");
$events_array = array();

foreach ($events as $event) {
    
    $start = "".date(strtotime($event->startTime))."";
    $title = $event->title;
    
    $events_array[] = array(
        'title' => $title, 
        'date' => $start
    );
}

$events_json = json_encode($events_array, true);
echo $events_json;

 

Share this post


Link to post
Share on other sites

the problem is that you have an array, but the items in the array are \ProcessWire\Page objects, so those can't directly map to a json encode.

you probably need to cycle through the pages you want and create the array manually. Alternately you could have a look at the GraphQL module, which i think some devs are using to get json data to the frontend.

  • Like 3

Share this post


Link to post
Share on other sites

Thank you @Zeka for this thread I just realized that I had this already open in a tab but waaaaaay too far on the right hand side of the window, I will try to fit the example in to my project.
But first I will have a look into GraphQL because this might also help me with future requirements. 

Share this post


Link to post
Share on other sites

For simple json outputs, you can use WireArray::explode and json_encode() or wireEncodeJSON() methods

https://processwire.com/api/ref/wire-array/explode/

$myPages = $pages->find('template=basic-page');
// extract required fields into plain array
$data = $myPages->explode(['title', 'created']);
echo wireEncodeJSON($data);
  • Like 6

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By dragan
      I'm puzzled by something I thought would be rather easy:
      I want to send a request to a PW page. It's POST, and I define a header, and send data as JSON.
      I need to send data in the following format:
      $ POST https://mysite.com/foo/bar/ {"headers": {"Authorization": "Bearer API_KEY", "Content-Type": "application/json"}, "body": {"fields": {"Name": "<get name>", "Department": "<get team>", "Home Address": "<get address>", "Phone #": "<get phone>", "Personal Email Address": "<get email>", "Birthday": "<get birthday>", "Date Added": "<call>currentDate</call>" }}} This is supposed to be sent via a Chatbot engine (Dexter).
      In the PW page that should handle this, $_POST is always empty, as is $_REQUEST. Same for PW's $input or if ($config->ajax) {}.
      I get the header, but no data.
      So I dug deeper, and tried this:
      @ini_set("allow_url_fopen", true);
      @ini_set("always_populate_raw_post_data", true);
      $data = json_decode(file_get_contents('php://input'), true);
      $d    = print_r($data, true); // I store this, along with the header infos and timestamp in a PW page-field (instead of using file_put_content)
      I checked page permissions, I made sure I use pagename/, i.e. with trailing slash only, to avoid stripping the header away due to redirects (which somebody in an older forum thread once highly suggested).
      I tried to send the same stuff that the chatbot does via CURL. Nothing. PW error logs don't report anything (site is still in dev-mode).
      PW 3.0.81 - everything else runs just fine.
      Any ideas what I should change? Any more PHP/Apache settings maybe?
      Help is highly appreciated.
       
    • By thomasaull
      I recently started to build Vue SPAs with ProcessWire as the backend, connected with a REST API. Thanks to code and the help of @LostKobrakai (How to use FastRoute with ProcessWire) and @clsource (REST-Helper) I got it up and running pretty quickly and now have put all of it in a site profile for others to use. It includes the REST API with routing for different endpoints, JWT Auth and a simple Vue SPA which shows the process of logging in a user (nevertheless, you don't have to use the Vue part, the API will work on it's own).
      Check it out here: https://github.com/thomasaull/RestApiProfile
      I'm pretty sure, it's not the perfect or most sophisticsted solution, but it gets the job done for me…
      Feedback or Improvements are very welcome
    • By carrdesigns
      In the admin, I am trying to access data from a page that contains an inputfieldand autofill that data into the modal edit window for a new entry.
      For instance, I have a template which contains a PageTable field. When I add a new entry to the PageTable, I want to capture the ID from the originating admin page and add it to a field in the edit modal as a way of linking the new entry back to the originating page. The new PageTable entries are NOT children of the originating page, and cannot be for structural reasons. I have attached an image which I hope will help to clarify the basic result I want to achieve.
      Is there a practical means of accomplishing this? I've been able to achieve something similar with the ConnectPageFields module, but it does not work with PageTable fields. Any input would be much appreciated.

    • By Vinnie
      Hi all, Im trying to fill an options field in all the children of the parent page, after I save it. 
      the options field is configured as multiple select checkboxes. here's the code i have so far:
      $this->addHookAfter('Pages::saved', function($event) { $page = $event->arguments[0]; //set the page if($page->template == 'sport-verenigingen-overzicht') { //get the subcategories from the parent textarea, split on newline $subcats = preg_split('/[\n\r]+/', $page->subcats); //(also tried without imploding and adding the array, also doesnt work) $subcats = implode("|",$subcats); //get the children $children = $page->children(); foreach ($children as $child) { //set the options(sport_categorie is the options field) $child->sport_categorie = $subcats; $child->save('sport_categorie'); } //if i use a normal textfield instead of an optionsfield, //all the children have the correct data e.g: test1|test2|test3 //how to get the values into the options field?? } }); Hope you guys can help! Keep up the good work, I'm loving what you're doing with PW!!
    • By celfred
      Hello,
      Still in my 'teaching game'. Here's my problem : I 'find' all players with a request like

      $allPlayers = $pages->find("template=player"); [/code Then, I limit to players belonging to the team of the logged in player with [code] $teamPlayers = $allPlayers->find("team=$loggedPlayer->team");
      No problem so far. But my scoreboards rely on either :

      $allPlayers->getItemKey($loggedPlayer);
      or

      $teamPlayers->getItemKey($loggedPlayer);
      to find the logged player's position in the charts.
      On the 'global' newboard with scoreboards based upon $allPlayers, everything works as expected.
      BUT on my 'team' newsboard, even though I'm using $teamPlayers, the returned indexes are based upon $allPlayers. Am I clear ? In other words, I have a total of 125 players, and my logged player is 61 out of 125 regarding the number of places he freed. But in his particular team of 25 players, he sould be 15 whereas he's still 61
      I'd like to reset my indexes (and start back from 0), but I can't find my way out of this...
      If someone has a hint to help, I'd appreciate.
      I have a second part in my worry : I had a way around it by simply making another 'raw' request :

      $teamPlayers = $pages->find("team=$loggedPlayer->team");
      Then my team indexes were right, but I faced another issue : Reordering my wirearray according to the scoreboard I want usually worked fine (simple sort() based upon an integer field, for example, player's coins, player's karma...) and indexes were updated BUT resorting with places.count ('places' field is a pageArray) doesn't update the indexes returned by getItemKey and my logged player is always at the position he was when I first did my initial $pages->find() query  
      So my way around found its limit and that's why I'm posting here, after struggling with this for a couple of hours...
      Thanks in advance for the help.