Home » Php » php – Iterate over PDO::FETCH_GROUP array to output results by category

php – Iterate over PDO::FETCH_GROUP array to output results by category

Posted by: admin February 25, 2020 Leave a comment

Questions:

I am sure this is a very simple problem that I seem unable to get my head around. I want to display a list of links grouped on screen into their respective categories. I’m using bootstrap and the idea is to have each link category outputted in its own column with the links under the heading:

For example:

Cat 1 ——- Cat 2

—Link 1 —— Link 3 —

—Link 2 —— Link 4 —

I have two tables:

  • The first ‘links’ has the columns linkId, categoryId, linkTitle, linkDescription, linkUrl etc.
  • The second ‘linkcategories’ has the columns categoryId, categoryTitle, categoryDescription etc.

I am using PDO and using the following to get the data from the database:

public function getLinkCategories() {
  $this->db->query('SELECT categoryTitle, linkTitle, linkDescription, linkUrl 
                    FROM link 
                    INNER JOIN linkcategories ON linkCategories.categoryId = link.categoryId 
                    WHERE link.marked_for_delete != 1');
  $results = $this->db->resultSetGrouped();
  return $results;
}

I am then using the code below to pass the results back, spcifically I read that I should use PDO::FETCH_GROUP so that I can return rows into a nested array, where indexes will be unique values from the first column, and values will be arrays similar to ones returned by regular fetchAll(). So using:

//get results set as array of objects - grouped
public function resultSetGrouped() {
  $this->execute();
  return $this->statement->fetchAll(PDO::FETCH_GROUP);
}

My page is loaded with the following and I pass the data to the view:

public function index() {
  //get the links
  $links = $this->linkModel->getLinkCategories();
  $pageData = ['title' => 'Links • BM Intranet'];
  $data = ['pageData' => $pageData, 'linkCategories' => $links];
  $this->view('links/index', $data);
}

I think I should be able to use a foreach loop to display the results on the page but can’t get my head around naming the right parts. This is what is returned in $data.

Array
(
[pageData] => Array
    (
        [title] => Links • Intranet
    )

[linkCategories] => Array
    (
        [Unsorted] => Array //Unsorted is the category name
            (
                [0] => Array
                    (
                        [linkTitle] => a link title
                        [0] => a link title
                        [linkDescription] => This is an example of a link you can store. This is the external website
                        [1] => This is an example of a link you can store. This is the external website
                        [linkUrl] => https://www.asbcdef.co.uk/
                        [2] => https://www.abcdef.co.uk/
                    )

                [1] => Array
                    (
                        [linkTitle] => People
                        [0] => People
                        [linkDescription] => This is another link
                        [1] => This is another link
                        [linkUrl] => https://www.efgjk.co.uk/people/
                        [2] => https://www.efgjk.co.uk/people/
                    )

            )

    )

)

So the bit I am stuck on is taking the returned results above and making it display on the page like…

Cat 1 ——- Cat 2

—Link 1 —— Link 3 —

—Link 2 —— Link 4 —

I have so far…

foreach($data as $link) : ?>
<div class="col-lg-6 col-md-12 mb-5">
<div class="row">
  <div class="col lead border-bottom mb-2">
    <i class="fas fa-folder text-secondary"></i> <?php echo $link->linkCategories; ?>
  </div>
</div>
<div class="row">
  <div class="col">
    <a target="_blank" class="text-danger" href="<?php echo $category->url; ?>"><?php echo $category->linkTitle; ?></a>
    <span class="float-right text-secondary">Hits: <?php echo $category->hits; ?></span>
    <p mt-0>
      <?php echo $category->linkDescription; ?>
    </p>
  </div>
</div>

But this is not working as the properties are incorrect.

So it looks like I can use $link[0][‘linkTitle’] to get the data from the array – so could foreach through that I think. What I don’t know how to do now is get the category name (which equals – Unsorted – in this case) and have the links related to it underneath

How to&Answers:

Based on your current data groupings, in order to iterate over the groups and retrieve the category names, you would need to implement three foreach($array as $index => $values) iterations.

$data = array(
    'pageData' => array(
        'title' => 'Links • Intranet',
    ),
    'linkCategories' => array(
        'Unsorted' => array(
            array(
                'linkTitle' => 'a link title',
                0 => 'a link title',
                'linkDescription' => 'This is an example of a link you can store. This is the external website',
                1 => 'This is an example of a link you can store. This is the external website',
                'linkUrl' => 'https://www.asbcdef.co.uk/',
                2 => 'https://www.abcdef.co.uk/',
            ),
            array(
              'linkTitle' => 'People',
                0 => 'People',
                'linkDescription' => 'This is another link',
                1 => 'This is another link',
                'linkUrl' => 'https://www.efgjk.co.uk/people/',
                2 => 'https://www.efgjk.co.uk/people/',
            ),
        ),
        'Cat 2' => array(
            array(
              'linkTitle' => 'People',
                0 => 'People',
                'linkDescription' => 'This is another link',
                1 => 'This is another link',
                'linkUrl' => 'https://www.efgjk.co.uk/people/',
                2 => 'https://www.efgjk.co.uk/people/',
            ),
        )
    ),
);

Simple Iteration https://3v4l.org/KGcuv

As I am not aware how the $data['pageData'] array is expected in your desired output, I have omitted it’s iteration by iterating over the linkCategories directly, using $data['linkCategories']. I have also added an additional group, Cat 2 to demonstrate multiple categoryTitle groupings.

foreach ($data['linkCategories'] as $category => $links) {
    echo $category;
    foreach ($links as $link) {
        echo $link['linkTitle'];
    }
}

Result

Unsorted
a link title
People

Cat 2
People

Bootstrap Markup Iteration https://3v4l.org/Du4YR

For displaying each grouping as a separate column in bootstrap, you would need to alter the simple iteration with your desired markup, by utilizing the row and col-**-** classes to suit your desired appearance.
To produce a two-column listing I have used col-6, but you can change the grid sizes as desired.

<div class="row">
<?php foreach ($data['linkCategories'] as $category => $links) { ?>
    <div class="col-6">
    <div class="h6"><?php echo $category; ?></div>
    <?php foreach ($links as $link) { ?>
        <div class="row">
            <div class="col">
                <p>
                <a target="_blank" class="text-danger" href="<?php echo $link['linkUrl'] ?>"><?php echo $link['linkTitle']; ?></a>
                </p>
                 <p><?php echo $link['linkDescription']; ?></p>
             </div>
        </div>
    <?php } ?>
    </div>
<?php } ?>
</div>

Result https://jsfiddle.net/sayudjp0/

<div class="row">
  <div class="col-6">
    <div class="h6">Unsorted</div>
    <div class="row">
      <div class="col">
        <p>
          <a target="_blank" class="text-danger" href="https://www.asbcdef.co.uk/">a link title</a>
        </p>
        <p>This is an example of a link you can store. This is the external website</p>
      </div>
    </div>
    <div class="row">
      <div class="col">
        <p>
          <a target="_blank" class="text-danger" href="https://www.efgjk.co.uk/people/">People</a>
        </p>
        <p>This is another link</p>
      </div>
    </div>
  </div>
  <div class="col-6">
    <div class="h6">Cat 2</div>
    <div class="row">
      <div class="col">
        <p>
          <a target="_blank" class="text-danger" href="https://www.efgjk.co.uk/people/">People</a>
        </p>
        <p>This is another link</p>
      </div>
    </div>
  </div>
</div>