Intro To Magento 2, Part 4: Collections and CRUD

I’m still amazed at the number of young programmers who don’t know what “CRUD” is. A word like that sounds very academic to me. Magento 2 makes it fairly uniform and simple to do basic database functions within your collections.

1. What is CRUD?

CRUD is an acronym.

CReate
Update
Delete

Basically, make new content, update that content, and then delete that content.

2. What files will we need to modify?

You can reference Part 3 here. We’ll continue using the same code base, and add-on a little bit.

app/code/Danjoseph/Helloworld/Blocks/Helloworld.php
app/code/Danjoseph/Helloworld/Controller/Index/Index.php
app/code/Danjoseph/Helloworld/Controller/Crud/Create.php
app/code/Danjoseph/Helloworld/Controller/Crud/Update.php
app/code/Danjoseph/Helloworld/Controller/Crud/Delete.php
app/code/Danjoseph/Helloworld/etc/module.xml
app/code/Danjoseph/Helloworld/etc/frontend/routes.xml
app/code/Danjoseph/Helloworld/Model/Hello.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Hello.php
app/code/Danjoseph/Helloworld/Model/ResourceModel/Hello/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

As you can see, we’re going to add 3 new controllers. One for each of our CRUD functions. Here’s a list of the files we’ll add and modify.

app/code/Danjoseph/Helloworld/Controller/Crud/Create.php
app/code/Danjoseph/Helloworld/Controller/Crud/Update.php
app/code/Danjoseph/Helloworld/Controller/Crud/Delete.php
app/code/Danjoseph/Helloworld/view/frontend/templates/helloworld.phtml

3. What modifications do I need to make to my block?

We’ll need to update the template so we have a way to update/delete the existing greetings and add a new one.

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

<?php

$data = $block->getGreetings();

?>
<div class="my-greetings-header">
    <div class="my-greetings-list">
        <ul>
            <?php foreach($data as $greeting): ?>
                    <li>
                        <form action="/helloworld/crud/update" method="post">
                            <input type="hidden" name="greetingsid" value="<?php echo $greeting->getGreetingsId(); ?>">
                            <input type="text" name="greetingtext" value="<?php echo $greeting->getGreetingText(); ?>">
                            <input type="submit" value="update">
                        </form>
                        [<a href="/helloworld/crud/delete?greetingid=<?php echo $greeting->getGreetingsId(); ?>">delete</a>]
                    </li>
            <?php endforeach; ?>
        </ul>
        <ul>
            <form action="/helloworld/crud/create" method="post">
                <li><input type="text" name="greeting_text"> <input type="submit" value="create"></li>
            </form>
        </ul>
    </div>
</div>

Just like last part, you can style this on your own, and I know this isn’t the greatest HTML structure. Let’s focus on the code and Magento.

Notice we’re putting forms around each of the line items, and then finally a blank form at the very end. Take note of the URL path that we’re sending each click too. Think back to Part 1 when we created our module and Index controller. We’re going to accomplish our CRUD functions with the use of more controllers.

Helloworld = module namespace
Crud = path in the Controllers folder
Create/Update/Delete = file name minus .php from the Crud path.

4. How do I get this to working in the PHP code?

The three controllers are all pretty similar. Let’s start with create.

app/code/Danjoseph/Helloworld/Controller/Crud/Create.php

<?php

namespace Danjoseph\Helloworld\Controller\Crud;

use Magento\Framework\App\Action\Context;

class Create extends \Magento\Framework\App\Action\Action
{
    protected $scopeConfig;

    public function __construct(
        Context $context,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    )
    {
        $this->scopeConfig = $scopeConfig;

        parent::__construct($context);
    }
    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();
        $params         = $this->getRequest()->getParams();
        $newGreeting    = $this->_objectManager->create('Danjoseph\Helloworld\Model\Helloworld');

        $newGreeting->setData( $params );
        $newGreeting->save();

        return $resultRedirect->setPath('helloworld/index/index');
    }
}

Let’s explain some of the new things here.

First, $params. You’re simply grabbing your POST data. You can access them just like any other array. $params[‘name’]. In our case, we’re submitting “greeting”, so you would be able to see that in $params[“greeting”].

Just like our Index Controller, execute() is what Magento will “run” when it instantiates your class.

Here’s update:

app/code/Danjoseph/Helloworld/Controller/Crud/Update.php

<?php

namespace Danjoseph\Helloworld\Controller\Crud;

use Magento\Framework\App\Action\Context;

class Update extends \Magento\Framework\App\Action\Action
{
    protected $scopeConfig;

    public function __construct(
        Context $context,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    )
    {
        $this->scopeConfig = $scopeConfig;

        parent::__construct($context);
    }
    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();

        $params = $this->getRequest()->getParams();
        $model  = $this->_objectManager->create('Danjoseph\Helloworld\Model\Helloworld');

        $model->load( $params['greetingid'] );
        $model->setGreetingText( $params['greetingtext'] );
        $model->save();

        return $resultRedirect->setPath('helloworld/index/index');
    }
}

Update is a lot like save, except you have to load up the greeting you want to modify.

$model->load( $params['greetingid'] );

From there, you use the setters built into Magento’s framework to set your data.

$model->setGreetingText( $params['greetingtext'] );

And finally, you save everything.

$model->save();

Here is delete:

app/code/Danjoseph/Helloworld/Controller/Crud/Delete.php

<?php

namespace Danjoseph\Helloworld\Controller\Crud;

use Magento\Framework\App\Action\Context;

class Delete extends \Magento\Framework\App\Action\Action
{
    protected $scopeConfig;

    public function __construct(
        Context $context,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    )
    {
        $this->scopeConfig = $scopeConfig;

        parent::__construct($context);
    }
    public function execute()
    {
        $resultRedirect = $this->resultRedirectFactory->create();

        $params = $this->getRequest()->getParams();
        $model  = $this->_objectManager->create('Danjoseph\Helloworld\Model\Helloworld');

        $model->load( $params['greetingid'] );
        $model->delete();

        return $resultRedirect->setPath('helloworld/index/index');
    }
}

Just like update, you load up your item, and then instead of save(), you delete().

Clear out your cache and generations folders:

% rm -rf var/generation
% php bin/magento cache:clean

That’s all there is to CRUD functions in Magento 2. You don’t necessarily have to break them up into different controllers, but I find it a clean way to keep things organized. For the purpose of this tutorial, it is also a clear way to explain things.

See what you can do with your collections. Break them apart, add new functions, add filtering. You now have all the basic tools to do a lot of fun stuff with the database.

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.