¡Oye! Mi nombre es Pavel y estoy haciendo desarrollo de backend. Hoy veremos las colecciones en Magento 2 (en lo sucesivo, M2). A pesar de la aparente simplicidad de implementación y el propósito intuitivo, esta esencia está plagada de varios obstáculos no obvios que afectan el rendimiento y, a veces, la capacidad misma del código para funcionar.
, , .
!
M2
, , 2 — -, , : , , .
- , :
<?php
declare(strict_types=1);
namespace RSHB\WhiteRabbit\Model\ResourceModel\WhiteRabbit;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use RSHB\WhiteRabbit\Model\ResourceModel\WhiteRabbit as WhiteRabbitResource;
use RSHB\WhiteRabbit\Model\WhiteRabbit as WhiteRabbitModel;
/**
* Class Collection
* @package RSHB\WhiteRabbit\Model\ResourceModel\WhiteRabbit
*/
class Collection extends AbstractCollection
{
/**
* {@inheritDoc}
*/
protected function _construct()
{
$this->_init(
WhiteRabbitModel::class,
WhiteRabbitResource::class
);
}
}
, -, . . , .
, :
$collection = $this->whiteRabbitCollectionFactory->create();
:
$collection->addFieldToFilter('name', $name);
xdebug. , _items
, , . ?
, M2-. sql . , , , — ORM, . , , :
$collection->getSelect()->__toString()
:
SELECT main_table. FROM rshb_white_rabbit AS main_table WHERE (name = 'White Rabbit')
, WHERE
. SELECT
_initSelect()
( ).
, , , .
: : . SQL , .
, — load()
. , xdebug:
. load()
, foreach
( , ArrayAccess
):
$collection = $this->whiteRabbitCollectionFactory->create();
$name = 'White Rabbit';
$collection->addFieldToFilter('name', $name);
foreach ($this->collection as $rabbit) {
//stop point
}
. !
, load()
? , . , load()
, .
: .
. ,
:
$collection = $this->whiteRabbitCollectionFactory->create();
$name = '%Rabbit';
$collection->addFieldToFilter('name', [‘like’ => $name]);
$collection->load();
//stop point 1
SELECT main_table.* FROM rshb_white_rabbit AS main_table WHERE (name LIKE '%Rabbit')
:
$ids = [1, 2];
$collection->addFieldToFilter('id', [‘in’ $ids]);
//stop point 2
$collection->clear();
$collection->load();
, :
SELECT `main_table`.* FROM `rshb_white_rabbit` AS `main_table` WHERE (`name` LIKE '%Rabbit') AND (`id` IN (1, 2))
, :
, , . clear()
, , load()
:
. load()
, , . clear()
load()
foreach
:
. , clear()
, .
:
if (count($collection)) {
//do something…
}
, , , count ( ArrayAccess
Countable
, ). .
, . count
, .. . , - , , count
$collection->getSize()
. :
SELECT COUNT(*) FROM `rshb_white_rabbit` AS `main_table` WHERE (`name` LIKE '%Rabbit') AND (`id` IN (1, 2))
.
, , .
, , , , COUNT
:
If ($collection->getSize()) {
foreach ($collection as $item) {
//Do something
}
}
foreach ($collection as $item) {
//do nothing if collection is empty
}
, , . , , , , , - .
:
$collection = $this->collectionFactory->create();
$name = '%Rabbit';
$collection->addFieldToFilter('name', [‘like’ => $name]);
$item = $collection->getFirstItem();
:
;
( , ).
, : , , , :
SELECT main_table.* FROM rshb_white_rabbit AS main_table WHERE (name LIKE '%Rabbit')
, , :
$collection = $this->collectionFactory->create();
$name = '%Rabbit';
$collection->addFieldToFilter('name', [‘like’ => $name]);
$collection->addOrder(‘name’, ASC);
$collection->setPageSize(1);
$item = $collection->getFirstItem();
SELECT `main_table`.* FROM `rshb_white_rabbit` AS `main_table` WHERE (`name` LIKE '%Rabbit') ORDER BY name ASC LIMIT 1
AND OR condition
:
$collection = $this->whiteRabbitCollectionFactory->create();
$name = '%Rabbit';
$collection->addFieldToFilter('name', [‘like’ => $name]);
$ids = [1, 2];
$collection->addFieldToFilter('id', [‘in’ $ids]);
SQL-:
SELECT `main_table`.* FROM `rshb_white_rabbit` AS `main_table` WHERE (`name` LIKE '%Rabbit') AND (`id` IN (1, 2))
, AND
.
OR
, :
$collection = $this->whiteRabbitCollectionFactory->create();
$name = '%Rabbit';
$ids = [1, 2];
$collection->addFieldToFilter(
['name', 'id'],
[
['like' => $name],
['in' => $ids]
]
);
SQL-:
SELECT `main_table`.* FROM `rshb_white_rabbit` AS `main_table` WHERE ((`name` LIKE '%Rabbit') OR (`id` IN (1, 2)))
, .
, , :
PHP Fatal error: Allowed memory size of XXXX bytes exhausted (tried to allocate XXXX bytes) in vendor/magento/zendframework1/library/Zend/Db/Statement/Pdo.php on line 228
.
, :
$collection = $this->collectionFactory->create();
$name = '%Rabbit';
$lastId = 500;
$collection->addFieldToFilter('name', [‘like’ => $name]);
$collection->addFieldToFilter('id', [‘gt’ => $lastId]);
$collection->addOrder(‘id’);
$collection->setPageSize(500);
.
walk()
Magento\Framework\Model\ResourceModel\Iterator
:
public function doAnything()
{
...
$this->iterator->walk(
$collection->getSelect(),
[[$this, 'callback']]
);
}
public function callback($args)
{
//do something
}
, ( ).
, _initSelect()
. . join` :
<?php
declare(strict_types=1);
namespace RSHB\WhiteRabbit\Model\ResourceModel\WhiteRabbit;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use RSHB\WhiteRabbit\Model\ResourceModel\WhiteRabbit as WhiteRabbitResource;
use RSHB\WhiteRabbit\Model\WhiteRabbit as WhiteRabbitModel;
/**
* Class Collection
* @package RSHB\WhiteRabbit\Model\ResourceModel\WhiteRabbit
*/
class Collection extends AbstractCollection
{
/**
* {@inheritDoc}
*/
protected function _construct()
{
$this->_init(
WhiteRabbitModel::class,
WhiteRabbitResource::class
);
}
/**
* @return Collection|void
*/
protected function _initSelect()
{
parent::_initSelect();
$this->getSelect()->join(
['another_white_rabbit' => 'rshb_another_white_rabbit'],
'main_table.id = another_white_rabbit.white_rabbit_id',
['another_name' => 'another_white_rabbit.name']
);
return $this;
}
}
, .
, .
getSize()
count()
( , ).
(
setPageSize()
) , .
, :
// :
$collection->addFieldToSelect('*');
// :
$collection->addFieldToSelect(['first', 'second', 'third']);
//, :
$collection->getFieldValues('somefield');
, .
, .
Connection
:
/** @var \Magento\Framework\App\ResourceConnection $connection **/
$connection = $this->connection->getConnection();
$tableName = $this->connection->getTableName('rshbwhite_rabbit’);
$sql = "SELECT * FROM $tableName";
$result = $connection->fetchAll($sql);
, — .
2. , , .
. . !