Hello again
I am working on the implementation of an audio player with amplitude.js.
I need to create a JSON with a structure field. I followed the docs about how calling simple field but I don’t know how to do with structure fields…
This is my try
<?php
if(!r::ajax()) go(url('error'));
header('Content-type: application/json; charset=utf-8');
$datastructure = $pages->find('projets')->children()->visible()->addresses()->toStructure();
$data = $datastructure->flip()->paginate(10);
$json = array();
foreach($data as $article) {
$json[] = array(
'artist' => (string)$article->artist(),
'name' => (string)$article->name(),
'album' => (string)$article->album(),
'url' => (string)$article->file()->url(),
);
}
echo json_encode($json);
?>
and my blueprint is
addresses:
label: Contributions
type: structure
entry: >
CONTRIBUTEUR : {{album}}<br />
ARTISTE : {{artist}}<br />
NOM : {{name}}<br />
DATE : {{time}}<br />
FICHIER : {{fichier}}
fields:
album:
label: Contributeur
type: text
icon: user
width: 1/2
artist:
label: Artiste
type: text
icon: microphone
width: 1/2
name:
label: Nom de la chanson
type: text
icon: music
time:
label: Date
type: date
format: DD/MM/YYYY
default: today
fichier:
label: Fichier audio
type: select
options: files
icon: file-audio-o
This is not possible, you can only call addresses()
on a single page, not a collection.
You can, however, create a new collection from all address items using the following function:
function createNewStructure($pages, $field) {
$structure = new Structure();
$key = 0;
foreach($pages as $p) {
foreach($p->$field()->toStructure() as $item) {
$structure->append($key, $item);
$key++;
}
}
return $structure;
}
$projects = page('projets')->children()->visible();
$items = createNewStructure($projects, 'addresses');
dump($items);
You can then loop through the items as usual.
$json = array();
foreach($items as $item) {
$json[] = array(
'artist' => (string)$item->artist(),
'name' => (string)$item->name(),
'album' => (string)$item->album(),
'url' => (string)$item->file()->url(),
);
}
echo json_encode($json);
If you don’t want the escaped slashes in your URLs, use the JSON_UNESCAPED_SLASHES
flag:
$data = json_encode($json, JSON_UNESCAPED_SLASHES);
Thank you for this piece of code, I didn’t think I had to do that !
So, do you tell me to put everything in the same file ? (Currently, my projetsapi.php) Like so :
I tried but it didn’t work (contrary to basic fields). How to do some checks ?
function createNewStructure($pages, $field) {
$structure = new Structure();
$key = 0;
foreach($pages as $p) {
foreach($p->$field()->toStructure() as $item) {
$structure->append($key, $item);
$key++;
}
}
return $structure;
}
$projects = page('projets')->children()->visible();
$items = createNewStructure($projects, 'addresses');
dump($items);
$json = array();
foreach($items as $item) {
$json[] = array(
'artist' => (string)$item->artist(),
'name' => (string)$item->name(),
'album' => (string)$item->album(),
'url' => (string)$item->file()->url(),
);
}
My JS is quite simple
$.getJSON('projets/api', function(getTrack) {
$.each(getTrack, function(i, songs) {
});
Amplitude.init({
"songs": getTrack
});
console.log(getTrack);
});
What exactly does not work? Is there an error in the PHP? Or do you get errors in your JS console? Maybe the json output is not as expected? I’m not familiar with what Amplitude.js expects…
Sorry,
What I wanted to say is that before using your script, the music player was working fine with my previous code, calling the JSON from simple fields.
With your code, the music player doesn’t work, and if I do alert(getTrack);
into the JS, I don’t see anything. (I don’t know how to use console.log
)
I was expecting to have something like
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]....
as it was previously.
PS : I’m trying to have this kind of structure :
{
"name": "Song Name 1",
"artist": "Artist Name",
"album": "Album Name",
"url": "myadress../song/url.mp3",
},
{
"name": "Song Name 2",
"artist": "Artist Name",
"album": "Album Name",
"url": "myadress../song/url.mp3"
},
{
"name": "Song Name 3",
"artist": "Artist Name",
"album": "Album Name",
"url": "myadress../song/url.mp3"
}
I don’t know, from what can see in the amplitude docs, the output is ok:
Amplitude.init({
"songs": [
{"artist":"Artist 1","name":"Song 1","album":"Album 1","url":"http://localhost/kirby/content/1-projects/1-project-a/01_flower_of_kilkenny.mp3"},
{"artist":"Artist 2","name":"Song 2","album":"Album2","url":"http://localhost/kirby/content/1-projects/1-project-a/01_i_wish_i_had_someone_to_love_me.mp3"},
{"artist":"Artist 3","name":"Song 3","album":"Album3","url":"http://localhost/kirby/content/1-projects/2-project-b/01_working_man.mp3"}
]
});
But the URL probably isn’t, try:
'url' => (string)$item->fichier()->toFile()->url(),
No, (string)$item->fichier()->toFile()->url(),
doesn’t work better.
Just to be clear, this is the logic I’m looking for
{"artist":"Artist 1","name"...}, //From page 1 first structure field entry
{"artist":"Artist 2","name"...}, //From page 1 second structure field entry
{"artist":"Artist 3","name"...}, //From page 2 first structure field entry
// etc...
Please look for errors in your dev tools console, I can’t see these from remote unless your project is online somewhere.
What was your code before that did work (with the single field)?
Anyway, it works for me:
projectsapi.php:
<?php header('Content-type: application/json; charset=utf-8');
function createNewStructure($pages, $field) {
$structure = new Structure();
$key = 0;
foreach($pages as $p) {
foreach($p->$field()->toStructure() as $item) {
$structure->append($key, $item);
$key++;
}
}
return $structure;
}
$projects = page('projects')->children();
$items = createNewStructure($projects, 'addresses');
$json = array();
foreach($items as $item) {
$json[] = array(
'artist' => (string)$item->artist(),
'name' => (string)$item->name(),
'album' => (string)$item->album(),
'url' => (string)$item->fichier()->toFile()->url(),
);
}
$data = json_encode($json, JSON_UNESCAPED_SLASHES);
echo $data;
Script (note that I call the url via PHP here, only possible in the footer)
<?= js('assets/js/jquery.js') ?>
<?= js('assets/js/amplitude.min.js') ?>
<script>
var url = "<?= url('projects/api') ?>";
$.getJSON(url, function(getTrack) {
$.each(getTrack, function(i, songs) {
});
Amplitude.init({
"songs": getTrack,
"autoplay": true
});
});
Note that I’m not using any pagination here, and I don’t quite see the purpose of it in your code above.