Zen and the Art of FullStack Development

Making a Simple Cell in CakePHP 4

This tutorial covers the basics of creating a view cell based upon an "articles" table, similar to the one from the blog tutorial on CakePHP.org.  It is written using CakePHP 4.
Photo by Hal Gatewood on Unsplash

In this tutorial, we’re going to create a “recent articles” cell that can be used on the front page (or pretty much anywhere else) on your site. (Here, it’s designed to show a card-style posts page, much like an “archives” page in WordPress.) To get started, I recommend completing the Content Management tutorial from the official CakePHP.org site and using that project as your starting point because it will give you the “Articles” configuration that’s the basis of the examples. Also, for visuals, I’m using W3.css and one of the W3 color themes.

From your project’s root directory, bake a template for your new cell:

bin/cake bake cell Archive

This will create two files:


ArchiveCell.php is where the logic for your cell will go, and Archive/display.ctp is the default display template.

In the as-of-yet empty display method of ArchiveCell.php, we want to put in the necessary code to return the twelve most recent articles posted to our Articles table:

public function display()

        $articles = $this->Articles
            ->contain(['Users', 'Images'])
            ->where(['published' => true])
            ->order(['articles.modified' => 'DESC']);

        $this->set('articles', $articles);

In the code above, we’re bringing in the model for “Articles” and using Cake ORM (Object-Relational Mapping) to return the articles. The “contains” clause includes the linked table “Users,” which you should have if you completed the CakePHP CMS tutorial. (My “contains” also has an “Images” reference which you won’t have; we’ll address images in a future post. For now, just leave “Images” out of your “contains” reference.) We’re making sure that we only show articles that have been checked as “published,” limiting the query to twelve rows, and sorting them by the modified date in descending order.

Last, we set the template variable articles to contain our data. This allows us to show the data in the display.php file that was generated in template/cell/Archive by our “bake” command.

<div class="w3-container w3-padding-48">
    <?php $column_count = 99; ?>
    <?php foreach ($articles as $article): ?>
    <?php if ($column_count > 3) { ?>
    <div class="w3-row">
    <?php $column_count = 0;
    } ?>
        <div class="w3-margin w3-col l3">
            <div class="w3-card-4 w3-theme-dark w3-padding-24">
                <div class="w3-container w3-center">
                <?= $this->Html->image($article->image['url'], ['width' => '100%']); ?>
                <div class="w3-container">
                    <h3><?= h($article->title) ?></h3>
                    <p><?= (strlen($article->body) > 303) ? substr($article->body,0,300) . '...' : $article->body; ?></p>
                    <p><?= $this->Html->link(__('Full Article'), ['controller' => 'articles', 'action' => 'view', $article->id]) ?></p>
        <?php $column_count++; ?>
    <?php if ($column_count > 3) { ?>
    <?php } ?>
    <?php endforeach; ?>

In our display.php, we’re doing a foreach, using the new variable $article (passed in from ArchiveCell.php) to iterate through the passed-in $articles. Using w3.css, we’ve made a nice card layout. (Note that this also uses an image from my images table; as previously stated, I’ll describe how I added images in another post.)

Note also that there’s some code around $article->body to limit the display to 300 characters (with “…” if needed) and a “Full Article” link that will send viewers to the Articles controller’s View method so they can read the complete post.

Now, all we have to do is place our cell on a page. To do that, we simply need to include the following line anywhere on the page of our choosing:

<?= $this->cell('Archives') ?>

Viola! We have a functioning cell All of the logic needed to produce the content of the cell is conveniently encapsulated in ArchivesCell.php, preventing clutter in our main controller and allow us to follow DRY standards. Likewise the display.php houses the additional HTML and logic needed to display the cell’s contents without bogging down our home.php. The cell can be used throughout our application, with changes to the formatting and content being done in one place.



I've been a LAMP/LEMP nerd for decades, and I've always loved to write. Over the years, things that other people wrote have helped me thousands of times, and I enjoy being able to give back to our community.

Leave a Reply

About Me

Full-stack LAMP developer with extensive Linux, SQL, and Wordpress experience.

Recent Posts

Sign up for our Newsletter

(Right now there is no newsletter, but you’re welcome to sign up just the same!)