読み込みが終了しない場合は、しばらく待つか、リロードを行なってください。
If loading does not finish, wait for a while or reload.
エンジニア向けの情報を発信するブログです。
どなたでも発信できます。
お好きに利用していただれば幸いです。

📁 Customize\Controller\Admin\HogeController
<?php
namespace Customize\Controller\Admin;
use Customize\Entity\PiyoEntity;
use Eccube\Controller\AbstractController;
use Customize\Repository\FugaRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class HogeController extends AbstractController
{
private $fugaRepository;
public function __construct(
FugaRepository $fugaRepository
) {
$this->fugaRepository = $fugaRepository;
}
/**
* @Route("/%eccube_admin_route%/hoge/upload", name="admin_hoge_upload", methods={"POST"})
*/
public function upload(Request $request)
{
// requestからアップロードファイルを取得
$file = $request->files->get('csv_file');
// ファイルを読み込みでオープン
if (($fp = fopen($file, 'r')) !== false) {
// hugeRepositoryのallClearアクションで今のデータを全て削除する
$this->hugeRepository->allClear();
// csvファイルを一行ずつ取得
while (($line = fgetcsv($fp)) !== false) {
// PiyoEntityを新規に作成
$piyoEntity = new PiyoEntity();
// piyoEntityのnameプロパティにcsvファイルのname項目をセットする
$piyoEntity->setName($line['name']);
// entityManagerのpersistアクションで$piyoEntityをentityManagerの管理下に置く
$this->entityManager->persist($piyoEntity);
// 保存する
$this->entityManager->flush();
}
}
return $this->redirectToRoute('foo');
}
}
📁 Customize\Repository\FugaRepository
<?php
namespace Customize\Repository;
use Customize\Entity\PiyoEntity;
use Eccube\Repository\AbstractRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class FugaRepository extends AbstractRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, PiyoEntity::class);
}
// テーブル内を全て削除する
public function allClear()
{
$this->createQueryBuilder('p')
->delete()
->getQuery()
->getResult();
}
}
📁 Customize\Controller\Admin\HogeController
<?php
namespace Customize\Controller\Admin;
use Customize\Entity\PiyoEntity;
use Eccube\Controller\AbstractController;
use Customize\Repository\FugaRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class HogeController extends AbstractController
{
private $fugaRepository;
public function __construct(
FugaRepository $fugaRepository
) {
$this->fugaRepository = $fugaRepository;
}
/**
* @Route("/%eccube_admin_route%/hoge/upload", name="admin_hoge_upload", methods={"POST"})
*/
public function upload(Request $request)
{
// requestからアップロードファイルを取得
$file = $request->files->get('csv_file');
// ファイルを読み込みでオープン
if (($fp = fopen($file, 'r')) !== false) {
// hugeRepositoryのallClearアクションで今のデータを全て削除する
$this->hugeRepository->allClear();
// 👇 こいつを追加
$this->entityManager->clear(PiyoEntity::class);
// csvファイルを一行ずつ取得
while (($line = fgetcsv($fp)) !== false) {
// PiyoEntityを新規に作成
$piyoEntity = new PiyoEntity();
// piyoEntityのnameプロパティにcsvファイルのname項目をセットする
$piyoEntity->setName($line['name']);
// entityManagerのpersistアクションで$piyoEntityをentityManagerの管理下に置く
$this->entityManager->persist($piyoEntity);
// 保存する
$this->entityManager->flush();
}
}
return $this->redirectToRoute('foo');
}
}
📁 Customize\Repository\FugaRepository(変更なし)
<?php
namespace Customize\Repository;
use Customize\Entity\PiyoEntity;
use Eccube\Repository\AbstractRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class FugaRepository extends AbstractRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, PiyoEntity::class);
}
// テーブル内を全て削除する
public function allClear()
{
$this->createQueryBuilder('p')
->delete()
->getQuery()
->getResult();
}
}
📁 Customize\Controller\Admin\HogeController(変更なし)
<?php
namespace Customize\Controller\Admin;
use Customize\Entity\PiyoEntity;
use Eccube\Controller\AbstractController;
use Customize\Repository\FugaRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
class HogeController extends AbstractController
{
private $fugaRepository;
public function __construct(
FugaRepository $fugaRepository
) {
$this->fugaRepository = $fugaRepository;
}
/**
* @Route("/%eccube_admin_route%/hoge/upload", name="admin_hoge_upload", methods={"POST"})
*/
public function upload(Request $request)
{
// requestからアップロードファイルを取得
$file = $request->files->get('csv_file');
// ファイルを読み込みでオープン
if (($fp = fopen($file, 'r')) !== false) {
// hugeRepositoryのallClearアクションで今のデータを全て削除する
$this->hugeRepository->allClear();
// csvファイルを一行ずつ取得
while (($line = fgetcsv($fp)) !== false) {
// PiyoEntityを新規に作成
$piyoEntity = new PiyoEntity();
// piyoEntityのnameプロパティにcsvファイルのname項目をセットする
$piyoEntity->setName($line['name']);
// entityManagerのpersistアクションで$piyoEntityをentityManagerの管理下に置く
$this->entityManager->persist($piyoEntity);
// 保存する
$this->entityManager->flush();
}
}
return $this->redirectToRoute('foo');
}
}
📁 Customize\Repository\FugaRepository
<?php
namespace Customize\Repository;
use Customize\Entity\PiyoEntity;
use Eccube\Repository\AbstractRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;
class FugaRepository extends AbstractRepository
{
public function __construct(RegistryInterface $registry)
{
parent::__construct($registry, PiyoEntity::class);
}
// テーブル内を全て削除する
public function allClear()
{
// 👇 以下のように書き換え
foreach ($this->findAll() as $entity) {
$this->getEntityManager()->remove($entity);
}
}
}
📁 /vender/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php
// ~~ 省略
/**
* Persists an entity as part of the current unit of work.
*
* @param object $entity The entity to persist.
*
* @return void
*/
public function persist($entity)
{
$visited = [];
$this->doPersist($entity, $visited);
}
// ~~ 省略
$this->doPersist($entity, $visited);
📁 /vender/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php
// ~~ 省略
/**
* Persists an entity as part of the current unit of work.
*
* This method is internally called during persist() cascades as it tracks
* the already visited entities to prevent infinite recursions.
*
* @param object $entity The entity to persist.
* @param array $visited The already visited entities.
*
* @return void
*
* @throws ORMInvalidArgumentException
* @throws UnexpectedValueException
*/
private function doPersist($entity, array &$visited)
{
$oid = spl_object_hash($entity);
if (isset($visited[$oid])) {
return; // Prevent infinite recursion
}
$visited[$oid] = $entity; // Mark visited
$class = $this->em->getClassMetadata(get_class($entity));
// We assume NEW, so DETACHED entities result in an exception on flush (constraint violation).
// If we would detect DETACHED here we would throw an exception anyway with the same
// consequences (not recoverable/programming error), so just assuming NEW here
// lets us avoid some database lookups for entities with natural identifiers.
$entityState = $this->getEntityState($entity, self::STATE_NEW);
switch ($entityState) {
case self::STATE_MANAGED:
// Nothing to do, except if policy is "deferred explicit"
if ($class->isChangeTrackingDeferredExplicit()) {
$this->scheduleForDirtyCheck($entity);
}
break;
case self::STATE_NEW:
$this->persistNew($class, $entity);
break;
case self::STATE_REMOVED:
// Entity becomes managed again
unset($this->entityDeletions[$oid]);
$this->addToIdentityMap($entity);
$this->entityStates[$oid] = self::STATE_MANAGED;
break;
case self::STATE_DETACHED:
// Can actually not happen right now since we assume STATE_NEW.
throw ORMInvalidArgumentException::detachedEntityCannot($entity, "persisted");
default:
throw new UnexpectedValueException("Unexpected entity state: $entityState." . self::objToStr($entity));
}
$this->cascadePersist($entity, $visited);
}
// ~~ 省略
$oid = spl_object_hash($entity);
if (isset($visited[$oid])) {
return; // Prevent infinite recursion
}
$visited[$oid] = $entity; // Mark visited
$class = $this->em->getClassMetadata(get_class($entity));
// We assume NEW, so DETACHED entities result in an exception on flush (constraint violation).
// If we would detect DETACHED here we would throw an exception anyway with the same
// consequences (not recoverable/programming error), so just assuming NEW here
// lets us avoid some database lookups for entities with natural identifiers.
// 👇 こいつ
$entityState = $this->getEntityState($entity, self::STATE_NEW);
switch ($entityState) {
case self::STATE_MANAGED:
// Nothing to do, except if policy is "deferred explicit"
if ($class->isChangeTrackingDeferredExplicit()) {
$this->scheduleForDirtyCheck($entity);
}
break;
case self::STATE_NEW:
$this->persistNew($class, $entity);
break;
case self::STATE_REMOVED:
// Entity becomes managed again
unset($this->entityDeletions[$oid]);
$this->addToIdentityMap($entity);
$this->entityStates[$oid] = self::STATE_MANAGED;
break;
case self::STATE_DETACHED:
// Can actually not happen right now since we assume STATE_NEW.
throw ORMInvalidArgumentException::detachedEntityCannot($entity, "persisted");
default:
throw new UnexpectedValueException("Unexpected entity state: $entityState." . self::objToStr($entity));
}
$this->cascadePersist($entity, $visited);
case self::STATE_NEW: $this->persistNew($class, $entity); break;
case self::STATE_MANAGED:
// Nothing to do, except if policy is "deferred explicit"
if ($class->isChangeTrackingDeferredExplicit()) {
$this->scheduleForDirtyCheck($entity);
}
break;
$entityState = $this->getEntityState($entity, self::STATE_NEW);
/**
* Gets the state of an entity with regard to the current unit of work.
*
* @param object $entity
* @param int|null $assume The state to assume if the state is not yet known (not MANAGED or REMOVED).
* This parameter can be set to improve performance of entity state detection
* by potentially avoiding a database lookup if the distinction between NEW and DETACHED
* is either known or does not matter for the caller of the method.
*
* @return int The entity state.
*/
public function getEntityState($entity, $assume = null)
{
$oid = spl_object_hash($entity);
if (isset($this->entityStates[$oid])) {
return $this->entityStates[$oid];
}
if ($assume !== null) {
return $assume;
}
// State can only be NEW or DETACHED, because MANAGED/REMOVED states are known.
// Note that you can not remember the NEW or DETACHED state in _entityStates since
// the UoW does not hold references to such objects and the object hash can be reused.
// More generally because the state may "change" between NEW/DETACHED without the UoW being aware of it.
$class = $this->em->getClassMetadata(get_class($entity));
$id = $class->getIdentifierValues($entity);
if ( ! $id) {
return self::STATE_NEW;
}
if ($class->containsForeignIdentifier) {
$id = $this->identifierFlattener->flattenIdentifier($class, $id);
}
switch (true) {
case ($class->isIdentifierNatural()):
// Check for a version field, if available, to avoid a db lookup.
if ($class->isVersioned) {
return ($class->getFieldValue($entity, $class->versionField))
? self::STATE_DETACHED
: self::STATE_NEW;
}
// Last try before db lookup: check the identity map.
if ($this->tryGetById($id, $class->rootEntityName)) {
return self::STATE_DETACHED;
}
// db lookup
if ($this->getEntityPersister($class->name)->exists($entity)) {
return self::STATE_DETACHED;
}
return self::STATE_NEW;
case ( ! $class->idGenerator->isPostInsertGenerator()):
// if we have a pre insert generator we can't be sure that having an id
// really means that the entity exists. We have to verify this through
// the last resort: a db lookup
// Last try before db lookup: check the identity map.
if ($this->tryGetById($id, $class->rootEntityName)) {
return self::STATE_DETACHED;
}
// db lookup
if ($this->getEntityPersister($class->name)->exists($entity)) {
return self::STATE_DETACHED;
}
return self::STATE_NEW;
default:
return self::STATE_DETACHED;
}
}
public function getEntityState($entity, $assume = null)
{
$oid = spl_object_hash($entity);
if (isset($this->entityStates[$oid])) {
return $this->entityStates[$oid];
}
if ($assume !== null) {
return $assume;
}
// ~~ 省略
if (isset($this->entityStates[$oid])) {
return $this->entityStates[$oid];
}
return $this->entityStates[$oid];
if ($assume !== null) {
return $assume;
}
self::STATE_NEW // 2
private function doPersist($entity, array &$visited)
case self::STATE_MANAGED:
// Nothing to do, except if policy is "deferred explicit"
if ($class->isChangeTrackingDeferredExplicit()) {
$this->scheduleForDirtyCheck($entity);
}
break;
// 👇 こいつの処理にいくとUnitOfWorkの管理下に入る
case self::STATE_NEW:
$this->persistNew($class, $entity);
break;
public function getEntityState($entity, $assume = null)
{
$oid = spl_object_hash($entity);
// 👇 管理下に入らないentityはこの条件で捕まっている
if (isset($this->entityStates[$oid])) {
return $this->entityStates[$oid];
}
// 👇 こいつの処理にいくとUnitOfWorkの管理下に入る
if ($assume !== null) {
return $assume;
}

private function doPersist($entity, array &$visited)
switch ($entityState) {
// 👇 このcaseに処理が飛ぶ
case self::STATE_MANAGED:
// Nothing to do, except if policy is "deferred explicit"
if ($class->isChangeTrackingDeferredExplicit()) {
$this->scheduleForDirtyCheck($entity);
}
break;
case self::STATE_NEW:
$this->persistNew($class, $entity);
break;
case self::STATE_REMOVED:
// Entity becomes managed again
unset($this->entityDeletions[$oid]);
$this->addToIdentityMap($entity);
$this->entityStates[$oid] = self::STATE_MANAGED;
break;
case self::STATE_DETACHED:
// Can actually not happen right now since we assume STATE_NEW.
throw ORMInvalidArgumentException::detachedEntityCannot($entity, "persisted");
default:
throw new UnexpectedValueException("Unexpected entity state: $entityState." . self::objToStr($entity));
}
spl_object_hash
説明
この関数は、オブジェクトの一意な識別子を返します。この ID は、 オブジェクトを保存する際のハッシュのキーとして使えます。 また、オブジェクトが破棄されるまでは、オブジェクトを識別するための値としても使えます。 オブジェクトが破棄されると、そのハッシュが他のオブジェクトで再利用されてしまうことがあります。 この振る舞いは、spl_object_id() に似ています。
戻り値
現在存在する各オブジェクトに固有で、同一オブジェクトに対しては常に同じ値となる文字列を返します。
$this->entityManager->clear(PiyoEntity::class);