Save "dynamic" data belonging to user


#1

Hallo everybody

I have a question regarding saving sort of dynamic data that belongs to a user.
I am not sure on where to save those data (with an SQL database it would be easy, but I am not sure how to do it with kirby) and which way to save those.

The idea is to create a site that has several videos. Each user has to watch those tutorial videos and I would like to save the progress, e.g. save the time they stopped the video or if they have finished it. Later on this data is being used to see if the users have completed the videos, when etc.

So now my question: how can I save this data?
There will be new videos added so I wouldn’t want to use fixed fields.

My thinking so far was to extend the user to have a field where I save JSON data or a serialized array.
(Speaking of this: is this recommended? Is there a limit to the lenght in a kirby file?)

Or is there a ‘better’ or more ‘kirbyesque’ way?

Thanks!


#2

The way to do that would be either as structured (yaml) data (structure field) or as a serialized string or JSON in a custom user field, as you suggested. I don’t know of any file length limits, but your example doesn’t sound as if your were going to save thousands of entries per user?

Another option would be to save the data in a database, which can easily be done with Kirby, and for lots of data, I’d probably recommend that.


#3

thanks for the suuuuper quick reply!

No I think it will be about max 100 videos. So I guess this should be fine.
I was more wondering about the “width” of the file; JSON or serialized array are just one line.

Regarding the structure field: is there a way to “write” to them via the frontend?
I guess you mean using it as a key / value store: can I access those elements directly?
So far I have only used them in the panel for a non fixed number of page elements


#4

Yes, you can yaml::encode() an array and write to file using $page->update(). As regards accessing a value, you can use findBy(). Other than that, you can use (almost) all collection methods, including converting to JSON.

Here is an example function that writes yaml data to file:

function addToStructure($page, $field, $data = array()){
      $fieldData = page($page)->$field()->yaml();
      $fieldData[] = $data;
      $fieldData = yaml::encode($fieldData);
      try {
        page($page)->update(array($field => $fieldData));
        return true;
      } catch(Exception $e) {
        return $e->getMessage();
      }
    }

#5

Awesome! I will look into it :slight_smile:

Thanks for the, yet again, awesome support!


#6

No matter which way you do it, if at one point in time you think “oh, this is getting slow, I wish I’d used a database”, nothing will be lost and you can just add a database and write all the data into it :slight_smile:


#7

Hi, me again :slight_smile:
I tried to use the snippet you mentioned, but I can’t get it to work.

This is how I am trying to save the data:

if(r::is('POST')) {
	$field = 'video_data';
	$data = r::data();


	$fieldData = $site->user()->$field()->yaml();
	$fieldData[] = $data;
	$fieldData = yaml::encode($fieldData);
	$site->user()->update(array(
	  $field => $fieldData,
	));
}

But I keep getting Call to a member function yaml() on null as error :frowning:


#8

Did some research and found this


I changed my code to work with PHPs (un)serialize function.

But if I am missing something on how to use yaml(), all the better :slight_smile:


#9

Yes, I can reproduce this, seems to work differently for users. You could try this, but do test it thoroughly before using it in production (I just used some test data, so you would have to adapt this).

$field = 'video_data';
$data = array(
  'video_data' => 'Video 3',
  'video_test' => 'Test 3'
);
// convert data to array (because if field is empty, it just returns a string it we can't append to it)
$fieldData = (array)$site->user()->data()[$field];
// let's check if the first entry in the array is empty (this is the case if the field is empty)
if(empty($fieldData[0])) {
  $fieldData[0] = $data;
// else we append the data to the array
} else {
  $fieldData[] = $data;
}
// and update the field
$site->user()->update(array(
	  $field => $fieldData,
));

If anyone has a better idea, let us know.