11 posts by 3 authors in: Forums > CMS Builder
Last Post: January 16, 2019   (RSS)

By rez - January 15, 2019 - edited: January 16, 2019

I have 3 editors. 

  1. is Locations multi with name and address field.
  2. is multi with pdf uploads, 1 each record. Currently there are 3 PDF files / records
  3. is a multi where I assign 13 locations from multi 1 to different PDF files. Some locations will be assigned the same PDF.
    1. In this editor,  you select a PDF with a drop menu using the database option, num for location name for label
    2. You then assign locations with a checkbox list

I am listing the PDF files for locations like this (my code looks right in preview but bunches up in post? It isnt what i need anyway)

// load records from 'assign' list($assignRecords, $assignMetaData) = getRecords(array( 'tableName' => 'assign', 'loadUploads' => true, 'allowSearch' => false, )); // load records from 'pdf_menus' list($pdf_menusRecords, $pdf_menusMetaData) = getRecords(array( 'tableName' => 'pdf_menus', 'loadUploads' => true, 'allowSearch' => false, )); // load records from 'locations' list($locationsRecords, $locationsMetaData) = getRecords(array( 'tableName' => 'locations', 'loadUploads' => true, 'allowSearch' => false, )); <?php foreach ($assignRecords as $record1): ?> <p><strong>Locations:</strong> <?php echo join(', ', $record1['locations:labels']); ?><br/> <?php foreach ($pdf_menusRecords as $record2): ?> <?php foreach ($record2['pdf'] as $index => $upload): ?> <?php if($record1['pdf_menu']==$record2['num']):?> Upload Url: <?php echo htmlencode($upload['urlPath']) ?><br/> <?php endif ?> <?php endforeach ?> <?php endforeach ?> </p> <?php endforeach ?>

which comes out like this:

Locations:Beltsville, Capitol Heights, Frederick, Gaithersburg
Upload Url: /cmsb/uploads/menu-01.pdf

Locations:Glen Burnie, Hagerstown, Laurel, Olney, Oxon Hill
Upload Url: /cmsb/uploads/menu-02.pdf

Locations:Philadelphia, Takoma Park / Langley Park, Temple Hills
Upload Url: /cmsb/uploads/menu-03.pdf

Which I can make link to the PDF files, no problem.

However, the client wants it each location listed separately:

Beltsville: PDF link

Capital Heights: PDF lnk

Frederick:PDF Link


That way, with many locations, they can be in alphabetical order and easier to find with one long list. 

So I tried some code I have (can see in my previous forum posts, a long time ago) that uses portfolio categories and depending on the location URL selected, lists any checkmarked items assigned to categories. Unfortunately, it's a different situation.

I wish CMSB had some built in features for this type of thing. It seems common to have to manually use arrays, explode, etc. for checkboxes. Whether it is a portfolio, tags, etc. If we are all doing it enough, it would be great if the CMS handled it. If it's common, please build it in?

Anyway, any help is appreciated.

How can I list out each location in multi 1, then loop through each PDF seeing if it is checkmarked / assigned in multi 3, and displaying only the checkmarked PDF? 

Unless there is an easier way? All I need to keep is multi 1 and can start over. My point was to not have to upload a PDF per location because there are 13 locations and only 2 or 3 PDFs with more locations on the way. 

By rez - January 15, 2019

Attached a screen shot of the editor where you assign locations from one editor to pdfs from a 3rd.

Need to list out all locations with appropriate PDF. Currently, there would be no way to stop multiple PDFs being assigned to a location. I'm fine with that. An admin can look at the list on the display page and quickly see there should only be one. 


cmsb.JPG 50K

By Toledoh - January 15, 2019

Hi Res.

Could you just add a pick list to the locations editor?  The pick list could be multiple or single only.  Then just have a list view of the locations section?


Tim Forrest

Toledoh Enterprises


By daniel - January 16, 2019

Hi Rez,

I think that Tim's suggestion is probably the simplest way to achieve this sort of list, but as you've said, this may not be the most efficient for you to work with. However, the drawback is that the more efficient method is considerably more complex to represent on the front-end.

The following has not been fully tested and makes a few assumptions about how you've set up your lists and field names, but I believe should at least be close to what you're looking for:

// load records from 'assign' 
list($assignRecords, $assignMetaData) = getRecords(array( 'tableName' => 'assign', 'loadUploads' => true, 'allowSearch' => false, )); 
// load records from 'pdf_menus' 
list($pdf_menusRecords, $pdf_menusMetaData) = getRecords(array( 'tableName' => 'pdf_menus', 'loadUploads' => true, 'allowSearch' => false, )); 
// load records from 'locations' 
list($locationsRecords, $locationsMetaData) = getRecords(array( 'tableName' => 'locations', 'loadUploads' => true, 'allowSearch' => false, )); 

// group PDFs by num
$pdfsByNum = array_groupBy($pdf_menusRecords, 'num');


<?php foreach ($locationsRecords as $locationRecord): ?> 
    <strong><?php echo $locationRecord['title']; ?>:</strong> 

    <?php foreach ($assignRecords as $assignRecord): ?> 
        // unpack multi-select values for easier searching
        $assignedLocations = listValues_unpack($assignRecord['locations']);
      <?php if (array_search($locationRecord['num'], $assignedLocations) !== false): ?>
        <?php if (isset( $pdfsByNum[ $assignRecord['pdf_menu'] ] )): ?>
          <a href="<?php echo $pdfsByNum[ $assignRecord['pdf_menu'] ]['pdf']['urlPath']; ?>">PDF Download</a>
        <?php endif; ?>
      <?php endif; ?>
    <?php endforeach; ?>
<?php endforeach; ?>

The main things to note are:

  1. We start by looping through the locations
  2. We group the PDF records by their num to make it easy to find a PDF if we know its num
  3. Checking if a record is selected in a multi-select is more complicated (using listValues_unpack() and array_search())

I hope that's helpful; let me know if you have any questions about how this works!


PHP Programmer

By rez - January 16, 2019

Wow, ok. Thanks for this, it makes a perfect list. There are functions I didn't know existed or understand yet.

However, the upload links are currently coming out as "undefined index: urlPath"

They are uploads in the pdf multi, usually displayed with the standard code:

 <?php foreach ($pdf_menusRecords as $record): ?>
<?php echo htmlencode($record['title']) ?>:

  <?php foreach ($record['pdf'] as $index => $upload): ?>
   <a href="<?php echo htmlencode($upload['urlPath']) ?>" target="_blank">View PDF</a><br/>

  <?php endforeach; ?>
<?php endforeach; ?>

Also, doesn't the code have to loop through possible checkmarks,  which could even be more than one PDF per location by mistake? I'll be able to view the page and see that more than one is assigned by mistake but I'm lost adjusting your code.

Probably those assumptions you mentioned?

I will have questions about the functions but I guess i better wait on that or I'll confuse things more. 

By daniel - January 16, 2019

Hi Rez,

It looks like what's missing is the middle foreach in the snippet you just listed. Instead of "$record['pdf']" you would use "$pdfsByNum[ $assignRecord['pdf_menu'] ]['pdf']", so I think the modification would look something like this:

  <?php if (isset( $pdfsByNum[ $assignRecord['pdf_menu'] ] )): ?>
    <?php foreach ($pdfsByNum[ $assignRecord['pdf_menu'] ]['pdf'] as $index => $upload): ?>
      <a href="<?php echo htmlencode($upload['urlPath']) ?>" target="_blank">View PDF</a>
    <?php endforeach; ?>
  <?php endif; ?>

We are able to skip looping through possible checkmarks by using listValues_unpack(), which takes the values from a multi-select field (e.g. $assignRecord['locations']) and returns an array of all of the selected values. In this case, it should all be the location record nums. Then we use array_search() to effectively check "if the num for this location is in the array."

Let me know if you have any more questions. In the future, we'd love to create some documentation to make these additional functions more accessible to the average user!


PHP Programmer

By rez - January 16, 2019 - edited: January 16, 2019

Yes! I was assuming that's what was happening but couldn't get that loop working. I don't quite understand the nested looking array stuff. I was sure you created those functions for this type of thing and I didn't know about them. I searched and found them in the change log. 

Well, that was my next question. Documentation. Ok, is there anything I can run or test on functions that are in change logs or that I see in the forum that would sort of list out what they might do? 

If not, are there any snippets you can you show me here that might help me experiment with this setup to see more? If not, no worries, I will experiment and just ask specific questions later. I can sort of see whats happening, it's almost "readable" logic but not until I see it already done. I'm pretty sure I will end up understanding it more than %\t tab lists, explode and all of that. Embarrassingly, I get lost every time but have a collection that has worked in repeat situation with minor tweaks.

Working great and really cool, thanks.

By rez - January 16, 2019 - edited: January 17, 2019

Oh, or maybe I need to just to display the contents of the variables you are setting to see more. Something like that?

Confused: So if the unpack already figured out the checkboxes, what does the "isset" do here?

By daniel - January 16, 2019

Hi Rez,

A lot of these internal functions will have some short documentation or usage instructions right in the code if you're able to find where they are defined. array_groupBy() is in cmsb/lib/common.php on line 1204, and listValues_unpack() is in cmsb/lib/schema_functions.php on line 501. array_search() is a native PHP function and the documentation can be found here: http://php.net/manual/en/function.array-search.php

Also, a general tip that I find very helpful for testing is that you can use showme() on arrays, and var_dump() on any variable, to get a better representation of what's in them, like this:

showme( $foo ); // this is a helper function in CMSB; prints array contents
var_dump( $bar ); // this is a native PHP function; displays details of any variable (http://php.net/manual/en/function.var-dump.php)

When I'm trying out new code or functions, I find it helpful to use these functions to see a visual representation of my data at various points, such as before and after I use a function on it.

Hopefully, this gives you a good starting place!


PHP Programmer