We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 47047
    • 43 Posts
    Hello Folks!

    I have a grid of checkboxes for user's availability week (image attached), I'm not sure if, to save each checked checkbox as a extended field is a effective way (for consulting data)... or maybe creating a custom database table associated to user table or maybe another way?

    Thanks for you help!

    This question has been answered by m.engel. See the first response.

      @yulianita
      • 40706
      • 128 Posts
      If you plan to search through this data, i would strongly suggest to use an custom Table.
      I would create an table with the user and one field for each day, and use SET`s with 24 hour-values for every weekday.

      If you will just display this per User using the extended Field would be also viable.
        • 5430
        • 247 Posts
        JSON in extended field would be sufficient in my opinion, since it's a simple thing to grab/parse/manipulate JSON via snippet.
          • 3749
          • 24,544 Posts
          Another way to go would be to use files named with the user ID (e.g., user3.txt user22.txt). User extended fields are kind of a pain to work with and kind of slow. If you do use the extended fields, I second claytonk's suggestion to use a single field with the data in JSON or Serialize() form.

          To save the data, you could pull the checkbox data into an array, use serialize() on it (or json_encode()), and save it to the user's file. The advantage of serialize() is that the data string is much shorter. The advantage of json_encode() is that it's more human-readable (good during development, but no advantage later).

          Since you'll be getting an array showing the user's availability, you can use it to check the appropriate checkboxes in a read-only display for non-admins to see, and the same display in read-write mode for whoever sets the availability. Set the checkboxes with a placeholder tag in each checkbox input that you replace with ' checked="checked "' for the ones that should be checked.
            Did I help you? Buy me a beer
            Get my Book: MODX:The Official Guide
            MODX info for everyone: http://bobsguides.com/modx.html
            My MODX Extras
            Bob's Guides is now hosted at A2 MODX Hosting
            • 47047
            • 43 Posts
            I really appreciate your responses. I'll need to search through this data so I was reading about how is easy save as a json field but that can be slow when you need to query, so I decide make a custom table using CMP. The table (so far) has id, day, hour, everything it's okay but the problem is that my snippet is inserting just the last checkbox selected. I'm using an bidimensional array for day and hour.

            Snippet
            $package_path = $modx->getOption('core_path').'components/usravailability/model/';
            $modx->addPackage('usravailability', $package_path);
            $myRow = $modx->newObject('Usravailability');
            
            $availability = $hook->getValue('hour');
            foreach ($availability as $count => $day ) {
                foreach ($day as $hour) {
              
                    $data = array(
                        'id' => $id_usr,
                        'day' => $count,
                        'time' => $hour
                    );
                 $myRow->fromArray($data);
             
            if ( !$myRow->save() ) {
                $output .= '<p>Could not create row</p>';
            } else {
                $output .= '<p>Created row successfully</p>';
            }
                }   
                
            }
            


            Input form
            //for monday hour[0][], for tuesday hour[1][] ...
            <input type="checkbox" name="hour[0][]"  value="7:00">
            <input type="checkbox" name="hour[0][]"  value="8:00">
            <input type="checkbox" name="hour[0][]"  value="9:00">
            ...
            


            Sorry for my English, thank you for your help.
              @yulianita
              • 3749
              • 24,544 Posts
              Make sure each row has a different key. If they're all [0], you'll only get the last row.

                Did I help you? Buy me a beer
                Get my Book: MODX:The Official Guide
                MODX info for everyone: http://bobsguides.com/modx.html
                My MODX Extras
                Bob's Guides is now hosted at A2 MODX Hosting
              • discuss.answer
                • 40706
                • 128 Posts
                Your Problem is that you re-save one Object for every row, You have to create the new Objects inside the loop. Otherwise you will update that row for every value.
                Also you don't need fromArray(), just pass it as 2nd parameter, saves some rows.

                Also, be shure that "id" is not an uniq or primary key, if you want to have each timestamp in one row.

                $package_path = $modx->getOption('core_path') . 'components/usravailability/model/';
                $modx->addPackage('usravailability', $package_path);
                
                
                $availability = $hook->getValue('hour');
                foreach ($availability as $count => $day) {
                    foreach ($day as $hour) {
                        $myRow = $modx->newObject('Usravailability', array(
                            'id'   => $id_usr,
                            'day'  => $count,
                            'time' => $hour
                        ));
                        if (!$myRow->save()) {
                            $output .= '<p>Could not create row</p>';
                        } else {
                            $output .= '<p>Created row successfully</p>';
                        }
                    }
                
                }


                PS: maybe just cuttet in your paste, but $id_usr is undefined.

                For deleting all old Data from one User before saving new you could use this one-liner:
                $modx->removeCollection('Usravailability', array( 'id'   => $id_usr ));
                [ed. note: m.engel last edited this post 10 years, 2 months ago.]
                  • 47047
                  • 43 Posts
                  Thanks Michael! is exactly what I was looking for, it's working now, I appreciate, I am now working in retrieving these data from the table and sending it to the form.

                  Thanks again and thank you BobRay too.


                  Quote from: m.engel at Aug 12, 2016, 05:41 AM
                  Your Problem is that you re-save one Object for every row, You have to create the new Objects inside the loop. Otherwise you will update that row for every value.
                  Also you don't need fromArray(), just pass it as 2nd parameter, saves some rows.

                  Also, be shure that "id" is not an uniq or primary key, if you want to have each timestamp in one row.

                    @yulianita
                    • 47047
                    • 43 Posts
                    Quote from: BobRay at Aug 12, 2016, 02:05 AM
                    Make sure each row has a different key. If they're all [0], you'll only get the last row.


                    It's true Bob, I did this.

                    <?php
                    
                    $output = '';
                    $id = $modx->user->get('id');
                    $ravailability = $hook->getValue('hour');
                    
                    $package_path = $modx->getOption('core_path').'components/availability/model/';
                    $modx->addPackage('availability', $package_path);
                    $modx->removeCollection('UserAvailability', array( 'id_user' => $id ));
                    
                    $key = array_keys($ravailability);
                    
                    foreach ($key as $count => $day) {
                        foreach ($ravailability[$day] as $value) {
                             $myRow = $modx->newObject('UserAvailability', array(
                                'id_user' => $id,
                                'weekday' => $day,
                                'time' => $value
                            ));
                            if ( !$myRow->save() ) {
                                 $output .= '<p>Could not create row</p>';
                            } 
                            else {
                                $output .= '<p>Created row successfully</p>';
                            }
                        }   
                    }


                    This snippet is called through 'prehook UpdateProfile snippet', this info is been stored in my custom table, but is stored too as extended fields, do you know how can I prevent this?
                    Thanks for your help.
                      @yulianita
                      • 3749
                      • 24,544 Posts
                      You could try ClassExtender, but it might take some effort since your situation is more complex than just a list of extra fields.

                      If you got it working, it would make thing much faster (especially searching and sorting).
                        Did I help you? Buy me a beer
                        Get my Book: MODX:The Official Guide
                        MODX info for everyone: http://bobsguides.com/modx.html
                        My MODX Extras
                        Bob's Guides is now hosted at A2 MODX Hosting