Intro To Magento 2, Part 3: Collections

I remember the days of typing out all of my SQL queries. I enjoyed it. There was one time I even considered going the DBA route. Enter in modern times and the age of the ORM. This brings us to a talk about Magento 2 and how it uses collections.

Collections are Magento’s way of making database interaction uniform with the ways of the framework. I also like to believe that it makes things a bit easier and cleaner. There isn’t a need to write a bunch of getter and setter code if you don’t want or need too. Simply build a collection and you’ll have access to your tables and data.

1. What are our file additions?

Let’s expand on our file structure. You can pull up Part 2 for reference. We’re going to add a Model folder and some files.

app/code/Danjoseph/Helloworld/Blocks/Helloworld.php
app/code/Danjoseph/Helloworld/Controller/Index/Index.php
app/code/Danjoseph/Helloworld/etc/module.xml
app/code/Danjoseph/Helloworld/etc/frontend/routes.xml
app/code/Danjoseph/Helloworld/Model/Helloworld.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Helloworld.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Helloworld/Collection.php
app/code/Danjoseph/Helloworld/view/frontend/layout/helloworld_index_index.xml
app/code/Danjoseph/Helloworld/view/frontend/templates/helloworld.phtml
app/code/Danjoseph/Helloworld/Setup/InstallSchema.php
app/code/Danjoseph/Helloworld/registration.php

Here are just the new files from that list:

app/code/Danjoseph/Helloworld/Model/Helloworld.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Helloworld.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Helloworld/Collection.php
app/code/Danjoseph/Helloworld/Setup/InstallSchema.php

2. What is the right way to make a new database table?

Since you’re building a new collection in Magento, you’re going to want to establish a new database table. For this tutorial, I am using MySQL, the database server choice of Magento.

app/code/Danjoseph/Helloworld/Setup/InstallSchema.php

<?php

namespace Danjoseph\Helloworld\Setup;
 
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
 
class InstallSchema implements InstallSchemaInterface
{
	public function install( SchemaSetupInterface $setup, ModuleContextInterface $context )
    {
        $setup->startSetup();
 
        $table = $setup->getConnection()->newTable(
            $setup->getTable('danjoseph_greetings')
        )->addColumn(
            'greetings_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
            'Greetings ID'
        )->addColumn(
            'greeting_text',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            [],
            'Greeting Text'
        )->setComment(
            'Greetings Table'
        );
        $setup->getConnection()->createTable($table);
 
        $setup->endSetup();
}

Here we’re implementing Magento 2’s InstallSchemeIterface and creating our table.

All of your scripts will start with $setup->startSetup() and end with $setup->endSetup();

In between that, you can really add any valid options you want. Create attributes, block content, update things, etc. In our case, we’re going to create our database table to use with our collection. We’ll call it danjoseph_greetings. Always prefix your tables with your own label so you don’t interfere with other plugin’s tables and core tables.

The code is pretty clear. First, you’re going to build your object with newTable and addColumn methods. Then at the end you’ll run the createTable() method. getConnect() is your database object you can interface with for various things.

After we get all of our new code in place, you will run this from the command line:

% php bin/magento setup:upgrade

This will run your setup script.

3. How will I interface with this table?

Let’s build out the code to interface with our new table.

app/code/Danjoseph/Helloworld/Model/Helloworld.php

<?php

namespace Danjoseph\Helloworld\Model;

class Hello extends \Magento\Framework\Model\AbstractModel
{
    protected function _construct()
    {
        $this->_init('Danjoseph\Helloworld\Model\ResourceModel\Helloworld');
    }
}

This is a fairly simple script. You’re simply initializing your resource model.

app/code/Danjoseph/Helloworld/Model/ResourceModel/Helloworld.php

<?php

namespace Danjoseph\Helloworld\Model\ResourceModel;

class Helloworld extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    protected function _construct()
    {
        $this->_init( 'danjoseph_greetings', 'greetings_id' );
    }
}

This is another simple script. Here you’re extending the abstract database model, and initializing your table name and the column you want to base your queries off of. I suggest you use the id column.

app/code/Danjoseph/Helloworld/Model/ResourceModel/Helloworld/Collection.php

<?php

namespace Danjoseph\Helloworld\Model\ResourceModel\Helloworld;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    protected function _construct()
    {
        $this->_init(
            'Danjoseph\Helloworld\Model\Helloworld',
            'Danjoseph\Helloworld\Model\ResourceModel\Helloworld'
        );
    }
}

Finally, this is where we extend the abstract collection model, and initialize our model and resource model.

3. How do I use the collection?

Let’s go back to our block code and change it around.

app/code/Danjoseph/Helloworld/Block/Helloworld.php

<?php

namespace Danjoseph\Helloworld\Block;

use Magento\Framework\View\Element\Template;

class Helloworld extends \Magento\Framework\View\Element\Template
{
    public function __construct( \Magento\Framework\View\Element\Template\Context $context )
    {
        parent::__construct($context);
    }

    protected function _prepareLayout()
    {
        $this->pageConfig->getTitle()->set(__('My Greetings'));
    }

    public function getGreetings()
    {
        $this->_isScopePrivate = true;

        $objectManagerr   = \Magento\Framework\App\ObjectManager::getInstance();

        $greetingsFactory = $objectManagerr->create( 'Danjoseph\Helloworld\Model\Helloworld' );

        $data             = $greetingsFactory ->getCollection();

        return $data;
    }
}

Here we’re creating an object from the collection we just built. The collection will initialize and ultimate issue a query to the database

SELECT * FROM danjoseph_greetings

You will also have access to your getGreetings() function from the template.

Let’s modify our template.

app/code/Danjoseph/Helloworld/view/frontend/templates/helloworld.phtml

<?php

$data = $block->getGreetings();

?>
<div class="my-greetings-header">
    <div class="my-gretings-title">
        <h2><?php echo __("My Greetings"); ?></h2>
    </div>
    <div class="my-greetings-list">
        <ul>
        	<?php foreach($data as $greeting): ?>
        		<li><?php echo $greeting->getGreetingText(); ?></li>
        	<?php endforeach; ?>
        </ul>
    </div>
</div>

The first couple lines is getting the data from your collection through your getGreetings() function.

You can style this however you see fit. You’ll see this gives it a title, and a list of your greetings. You’ll need to go into your table and put some greetings in to see the list.

And that’s it!

You’ll want to run that command line script now:

% php bin/magento setup:upgrade

You will also need to upgrade your database schema:

% php bin/magento setup:db-schema:upgrade

And then clear out your generations folder:

% php rm -rf var/generations

Additionally, if you have cache on, clean that out:

% php bin/magento cache:clean

You now have a working collection to go along with your module and custom block. You can further expand on your collection and start to build out a really nice view for your new piece of the web site. We’ll talk more advanced things with collections in our next series. For now, play around and see what you can do between the block code and the collection. Get comfortable with just a simple table pull.

Written by Dan
Welcome to my blog! Here you'll find my collection of bible study lessons, book reviews, and other posts I feel inspired to write. I am a Christian currently serving at First Baptist Church of Northville in Northville, MI.