Im integrating Tipue search into my site, and I need to write JSON file which is a list of all the pages on the site. I will eventually put this into a hook so it runs on page save, but for now i just want to get it working in a page template before porting it into a hook.
My problem is i dont know how to format the json output. Its working but i need it formatted a certain way.
heres what ive got:
<?php
$items = $site->index()->filterBy('template', 'not in', ['search', 'error']);
$last = $items->last();
$sitepages = array($items);
// Write the file
$json_data = json_encode($sitepages);
file_put_contents('site-search.json', $json_data)
?>
and heres the how i need the json file structured:
// json format
{"pages": [
<?php foreach ($items as $searchlist): ?>
{"title": "<?= $searchlist->title()->html() ?>", "text": "<?= $searchlist->pageintro()->html() ?>", "tags": "<?php foreach($searchlist->seokeywords()->split(',') as $tag): ?><?= $tag ?> <?php endforeach ?>", "url": "<?= $searchlist->url() ?>"}<?php if($searchlist !== $last) echo ',' ?>
<?php endforeach ?>
]}
Any ideas how i can do this?
texnixe
October 16, 2017, 11:38am
3
<?php
$items = $site->index();
foreach($items as $item) {
$data[] = [
'title' => $item->title()->value(),
'text' => $item->text()->html()->value()
// more fields here
];
}
$sitepages = array('pages' => $data);
// Write the file
$json_data = json_encode($sitepages);
file_put_contents('site-search.json', $json_data)
?>
1 Like
Thanks @novacanye but i don’t think that helps. I need to write a json file, and it needs to be in a particular structure, not as RSS feed.
@texnixe Brilliant! Thats very close, thank you. Just two small minor tweaks needed. This is working:
<?php
$items = $site->index()->filterBy('template', 'not in', ['search', 'error']);
foreach($items as $item) {
$data[] = [
'title' => $item->title()->value(),
'text' => $item->pageintro()->html()->value(),
'tags' => $item->seokeywords()->split(','),
'url' => $item->url(),
];
}
$sitepages = array('pages' => $data);
// Write the file
$json_data = json_encode($sitepages);
file_put_contents('site-search.json', $json_data);
var_dump($json_data);
?>
However i need the tags item to strip the comma and not be wrapped in [], like this:
"tags": "Home Sweet Home",
And the URL item needs to be unescaped like this:
"url": "http://minerva.dev/projects"
texnixe
October 16, 2017, 12:13pm
6
The tags are no problem:
'tags' => str_replace(',', ' ', $item->seokeywords()),
or, if you prefer:
'tags' => implode(' ', $item->seokeywords()->split(',')),
URL, use the JSON_UNESCAPED_SLASHES flag:
$json_data = json_encode($sitepages, JSON_UNESCAPED_SLASHES);
1 Like
Ok so i have moved this code into a hook, but the file is not getting generated…do i have to do something different with the destination path in a hook?
kirby()->hook(['panel.page.create', 'panel.page.update', 'panel.page.hide'], function($page) {
$site = site();
$items = $site->index()->visible()->filterBy('template', 'not in', ['search', 'error']);
foreach($items as $item) {
$data[] = [
'title' => $item->title()->value(),
'text' => $item->pageintro()->html()->value(),
'tags' => str_replace(',', '', $item->seokeywords()),
'url' => $item->url(),
];
}
$sitepages = array('pages' => $data);
// Write the file
$json_data = json_encode($sitepages, JSON_UNESCAPED_SLASHES);
file_put_contents('site-search.json', $json_data);
});
The problem is your use of the $site
variable that is not defined in that context. Replace with site()
.
And you probably have to give it a path:
f::write(kirby()->roots()->index() . '/site-search.json', $json_data);
I fixed it with this…
$fileoutput = kirby()->roots()->index() . '/search.json';
file_put_contents($fileoutput, $json_data);
Oh but @texnixe your way might be better
and it was better… this works great… thanks for the help…
kirby()->hook(['panel.page.create', 'panel.page.update', 'panel.page.hide'], function($page) {
$items = site()->index()->visible()->filterBy('template', 'not in', ['search', 'error']);
foreach($items as $item) {
$data[] = [
'title' => $item->title()->value(),
'text' => $item->pageintro()->html()->value(),
'tags' => str_replace(',', '', $item->seokeywords()),
'url' => $item->url(),
];
}
$sitepages = array('pages' => $data);
// Write the file
$json_data = json_encode($sitepages, JSON_UNESCAPED_SLASHES);
$fileoutput = kirby()->roots()->index() . '/site-search.json';
f::write($fileoutput, $json_data);
});
I have cleaned this up a little and set some variables. However when i try to set the names of the fields to get data from in the array, it breaks.
c::set('ktipuefilename', 'search.json');
c::set('ktipuetempignoretype', 'template');
c::set('ktipuetempignore', ['search', 'error']);
kirby()->hook(['panel.page.create', 'panel.page.update', 'panel.page.hide'], function($page) {
$items = site()->index()->visible()->filterBy(c::get('ktipuetempignoretype'), 'not in', c::get('ktipuetempignore'));
foreach($items as $item) {
$data[] = [
'title' => $item->title()->value(),
'text' => $item->pageintro()->html()->value(),
'tags' => str_replace(',', '', $item->seokeywords()),
'url' => $item->url(),
];
}
$sitepages = array('pages' => $data);
// Write the file
$json_data = json_encode($sitepages, JSON_UNESCAPED_SLASHES);
$fileoutput = kirby()->roots()->index() . '/' . c::get('ktipuefilename');
f::write($fileoutput, $json_data);
});
Should I be able to do something like:
c::set('ktipuetitle', title());
and get it back with
'title' => $item->c::get('ktipuetitle')->html()->value(),
Is that possible?
texnixe
October 16, 2017, 3:59pm
12
Yes, but not as horrible as above:
// you have to use a string or a boolean or an array as argument
c::set('ktipuetitle', 'title');
// use a fallback here in case the option is not set
'title' => $item->{c::get('ktipuetitle', 'title')}()->html()->value(),
Wow. I have been told off…lol… Thanks
I actually tried that first bit but what i wasn’t aware of was the currly braces in the second part.
texnixe
October 16, 2017, 5:28pm
14
Sorry, didn’t want to be rude…
No worries, you would have to really go some to offend me
I think i might turn this into my first Kirby plugin… stay tuned…