array_groupBy and show categories labels.

6 posts by 3 authors in: Forums > CMS Builder
Last Post: April 14, 2021   (RSS)

By Mikey - April 13, 2021

Hello folks,

I have a section editor for uploading documents. As I create a new document record, I can assign one or multiple categories to the document using a multi-select dropdown. I am trying to sort all my documents into groupings by the categories assigned to the documents.

The code below works, but I am unable to get the categories' label to display... this code only works with the numeric value of the categories. I've tried everything I can think of to get the categories' labels to appear.

<?php $documentsGroupedRecords = array_groupBy($documentsRecords, 'categories', true); ?> 
    
<?php foreach ($documentsGroupedRecords as $cats => $records): ?>
    
<div class="small-12 medium-4 large-3 cell gray-panel media-panel">  
    <h3><?php echo $cats; ?></h3>
    
<?php foreach ($records as $record): ?>
    <?php foreach ($record['document'] as $upload): ?>
        <?php $recordTitle = ucwords(strtolower($record['title'])); ?>
    
    <div>
    <?php if($upload = (@$record['document'][0])){ // WORKS
    echo '<h5><a href="download.php?num='.$record['num'].'" >'.$recordTitle.'</a></h5>'; } ?>
    </div>  

    <?php endforeach; ?>
<?php endforeach; ?>
</div>
    
<?php endforeach ?>

I've tried the following with no luck.

<?php $documentsGroupedRecords = array_groupBy($documentsRecords, 'categories:labels', true); ?> 
<?php $documentsGroupedRecords = array_groupBy($documentsRecords, 'categories:label', true); ?> 

I also tried:

<h3><?php echo join(', ', $records['categories:labels']); ?></h3>
<h3><?php echo join(', ', $records['categories:label']); ?></h3>
<h3><?php echo join(', ', $records['categories']); ?></h3>

Nothing seems to work... maybe I've been looking at this too long.

Any suggestions on how I can get this working so that the categories' labels will appear between the Heading 3 html?

Thanks, Zicky

By Deborah - April 13, 2021

Hi, Zicky.

I've used the following code with success. It has the added benefit of not displaying a heading for categories that don't contain at least one record.

<?php $documentsByCategory = array_groupBy($documentsRecords, 'category', true); ?>
<?php foreach (getListOptions('documents', 'category') as $value => $label): ?>
<?php $documents = @$documentsByCategory[$value]; ?>
<?php if (!$documents) { continue; } // skip empty categories ?>

<h2><?php echo $label;?></h2>

<?php foreach ($documents as $document): ?>

<?php if ($document['document_pdf']): ?>
<?php foreach ($document['document_pdf'] as $index => $upload): ?>
<p><a href="<?php echo htmlencode($upload['urlPath']) ?><?php echo htmlencode($document['title']) ?></a></p>
<?php endforeach ?>
<?php endif ?>

<?php endif ?>
<?php endforeach ?>

<?php endforeach ?>

I'm hoping you'll be able to make something out of that. I believe I got assistance in the forum for this years ago, but can't locate the post.

Good luck!
Deborah

By Mikey - April 13, 2021

Hey Deborah,

No joy. I'm still unable to get it to work.

I copied and pasted your code, updated it to my field names but it wouldn't work. I think it has to do with the fact that my "categories" are a multi-value pillbox. I also tried quite a few various changes to the code you provided - but had no luck getting it to work.

Thanks for the suggestion. 

By Deborah - April 13, 2021

Zicky, sorry that didn't help, but you're probably on the right track re: multi-value categories being the challenge. I've not had experience with that yet.

I'll bow out now and look forward to a solution from another forum member or Interactive Tools.

~ Deborah

By Steve99 - April 14, 2021

Hey Zicky,

This code should work for what you're looking to accomplish (with using a multi-value category field):

<?php 
foreach (getListOptions('documents', 'categories') as $value => $label) {
    echo '<h2>'.$label.'</h2>';
    foreach ($documentsRecords as $document) {
        if (($document['document']) && (in_array($value, explode("\t",$document['categories'])))) {
            foreach ($document['document'] as $index => $upload) {
                echo '<p><a href="'.htmlencode($upload['urlPath']).'">'.htmlencode($document['title']).'</a></p>';
            }
        }
    }
}
?>

Let me know how you make out.

Best,
Steve

By Mikey - April 14, 2021 - edited: April 14, 2021

Thanks Deborah & Steve,

Between your two suggestions I came up with something that works... though I wouldn't say it's clean. Basically your suggestions worked, but the code was still showing categories - even if an available category was not assigned to a document. So I wrote a little comparison to find it there's a match and if YES, then show the category. I then wrapped it in some CSS masonry columns.

<div class="masonry">
<?php $documentsGroupedRecords = array_groupBy($documentsRecords, 'categories', true); ?>
<?php foreach ($documentsGroupedRecords as $cats => $records): ?> 

    <div class="brick">
        
    <?php foreach (getListOptions('documents', 'categories') as $value => $label): ?>
        <?php if ($value == $cats): ?>
            <h2><?php echo $label; ?></h2>
        <?php endif; ?>
    <?php endforeach ?>
        
    <?php foreach ($records as $record): ?>
        <?php foreach ($record['document'] as $upload): ?>
            <?php $recordTitle = ucwords(strtolower($record['title'])); ?>

                <?php if($upload = (@$record['document'][0])){
                echo '<h5><a href="download.php?num='.$record['num'].'" >'.$recordTitle.'</a></h5>'; } ?>
    
        <?php endforeach; ?>
    <?php endforeach; ?>
        
    </div>
<?php endforeach ?>
</div>

Here's the CSS

/* @media screen based on Foundation 6 framework */
/* Small only */
@media screen and (max-width: 39.9375em) {
  .masonry {
    column-count: 1;
    column-gap: 1em;
  }
  .brick {
    display: inline-block;
    padding: 0 0 1em;
    width: 100%;
  }
}
/* Medium only */
@media screen and (min-width: 40em) and (max-width: 63.9375em) {
  .masonry {
    column-count: 2;
    column-gap: 1em;
  }
  .brick {
    display: inline-block;
    padding: 0 0 1em;
    width: 100%;
  }
}
/* Large and up */
@media screen and (min-width: 64em) {
  .masonry {
    column-count: 3;
    column-gap: 1em;
  }
  .brick {
    display: inline-block;
    padding: 0 0 1em;
    width: 100%;
  }
}

Thanks,

Zicky