0

I have been trying to figure this out for 2 days. I created a custom collection for my module structured as follows

app/code/Morello/Customproducts/Model/CustomProducts.php

namespace Morello\Customproducts\Model;

use Magento\Framework\Model\AbstractModel;

class CustomProducts extends AbstractModel
{
    protected function _construct()
    {
        $this->_init('Morello\Customproducts\Model\ResourceModel\CustomProducts');
    }
}

app/code/Morello/Customproducts/Model/ResourceModel/CustomProducts.php

namespace Morello\Customproducts\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class CustomProducts extends AbstractDb
{
    protected function _construct()
    {
        $this->_init('customer_products', 'customproduct_id');
    }
}

app/code/Morello/Customproducts/Model/ResourceModel/CustomProducts/Collection.php

namespace Morello\Customproducts\Model\ResourceModel\CustomProducts;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;

class Collection extends AbstractCollection
{

    protected function _construct()
    {
        $this->_init('Morello\Customproducts\Model\CustomProducts', 'Morello\Customproducts\Model\ResourceModel\CustomProducts');
    }

}

In my observer I use the CustomProductsFactory and call methods on it. addFieldToSelect, addFieldToFilter, load, setData and save all work, but when I try to call the delete method to remove an entry in the table it throws a fatal error

Fatal error: Uncaught Error: Call to undefined method Morello\Customproducts\Model\ResourceModel\CustomProducts\Collection::delete() in etc...

What am I missing? The Collection class in the ResourceModel\CustomProducts folder extends the right framework class...

Any help is appreciated.

EDIT:

This is a very simplified version of my observer...

app/code/Morello/Customproducts/Observer/Backend/CustomerSaveAfter.php

namespace Morello\Customproducts\Observer\Backend;

use Magento\Framework\App\ObjectManager;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Morello\Customproducts\Model\CustomProductsFactory;

class CustomerSaveAfter implements ObserverInterface
{

    private $customProductsFactory;

    public function __construct(
        CustomProductsFactory $customProductsFactory
    )
    {
        $this->customProductsFactory = $customProductsFactory;
    }

    public function execute(Observer $observer)
    {
        $customerId = '1';
        $productsToRemoveFromCustomer = array(1, 3, 27);

        $customProductModel = $this->customProductsFactory->create();
        $customProductCollection = $customProductModel->getCollection();

        $customProductCollection
            ->addFieldToSelect('customproduct_id')
            ->addFieldToFilter(
                'customer_id',
                ['eq' => $customerId ]
            )->addFieldToFilter(
                'product_id',
                ['in' => $productsToRemoveFromCustomer ]
            )
            ->load();
            ->delete();
    }
}
1

the collection class does not have a delete method. Only the model and resource model classes do have this.

If you could further describe, what your observer should do, I could maybe provide further information

  • I added the observer's code to my question... Thank you! – Tony Morello Jan 26 '17 at 1:50
  • Oh... I think I got it... I am calling the getCollection() method on my model... But without that how do I select the fields to filter which results I want to delete? – Tony Morello Jan 26 '17 at 2:22
  • 1
    @Morello you can loop the data and delete the record one by one – MeenakshiSundaram R Jan 26 '17 at 3:33
  • @MeenakshiSundaramR Yes that's what I did in my answer below... in the last foreach loop... First I collect the array of ids and then I delete them one by one.. – Tony Morello Jan 26 '17 at 13:19
0

I solved my issue... I accepted David Verholen's answer as correct because indeed the Collection class does not have a delete() method, however I decided to post the solution to my issue so that it could be helpful to someone else.

I had to split the deletion process in 2 parts in the Observer::execute() method as follows:

public function execute(Observer $observer)
{
    $customerId = '1';
    $productsToRemoveFromCustomer = array(1, 3, 27);
    $customProductDeleteCollection = $this->customProductsFactory->create();

    $idToRemove = $customProductDeleteCollection
                      ->getCollection() // USE THE COLLECTION 
                      ->addFieldToSelect('customproduct_id') // TO SELECT PRIMARY ID
                      ->addFieldToFilter( // USE CONDITIONS
                          'customer_id',
                          ['eq' => $customerId ]
                      )->addFieldToFilter(
                          'product_id',
                          ['in' => $productsToRemoveFromCustomer ]
                      )
                      ->load() // LOAD QUERY
                      ->getItems(); // GET THE RETURNED ITEMS

    foreach ($idToRemove as $item){
        $customProductDeleteCollection  // GET THE MODEL AGAIN
        ->load($item->getData('customproduct_id')) // LOAD THE ITEM'S PRIMARY ID
        ->delete(); // ERASE IT FROM THE FACE OF THE EARTH...
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.