提问人:psylo66 提问时间:7/9/2012 最后编辑:halferpsylo66 更新时间:8/4/2014 访问量:5780
在 Symfony2 中$em->clear() 时出现未定义的索引错误
Undefined index error upon $em->clear() in Symfony2
问:
我编写了一个 Symfony 命令来从 API 导入一些数据。它有效,但问题是当我在数据库中插入一个大的 JSON 时,我的 PHP 内存使用量会增加。我的 unitOfWork 在每次活动导入后增加“2”。
我已经取消了所有使用过的对象,并且当您想进行大规模批处理时,我已经阅读了 Symfony2 的文档:http://www.doctrine-project.org/blog/doctrine2-batch-processing.html
但是当我使用我的实体管理器时,会出现以下错误:$em->clear()
注意:未定义索引:0000000007b56ea7100000000e366c259 在应用程序路径\供应商\doctrine\lib\Doctrine\ORM\UnitOfWork.php行 2228
这是我的完整代码:
/**
* @see Command
*/
protected function configure() {
$this
->setName('ks:user:runkeepersync')
->setDescription('Synchroniser les activités d\'un utilisateur runkeeper')
->setDefinition(array(
new InputArgument('access_token', InputArgument::REQUIRED, 'Access token'),
))
}
/**
* @see Command
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$accessToken = $input->getArgument('access_token');
$em = $this->getContainer()->get('doctrine')->getEntityManager();
$UserHasServices = $em->getRepository('KsUserBundle:UserHasServices')->findOneByToken($accessToken);
if (!is_object($UserHasServices) ) {
echo "Impossible de trouver l'utilisateur qui possède le jeton ".$accessToken."";
}
$user = $UserHasServices->getUser();
$service = $UserHasServices->getService();
echo "avant de requérir l'api : ".memory_get_usage()."\n";
try {
$rkApi = $this->getContainer()->get('ks_user.runkeeper');
$rkApi->setAccessToken($accessToken);
$activities = $rkApi->getFitnessActivities(0,25);
$nbParPages = 25;
$nomberActivitites = $activities->size;
$aActivities = $activities->items;
$nbPages = floor ($nomberActivitites/$nbParPages);
$aEndurance = array("Running", "Cycling", "Mountain Biking", "Walking", "Hiking", "Downhill Skiing", "Cross-Country Skiing", "Snowboarding", "Skating","Wheelchair", "Rowing", "Elliptical", "Other");
$aEnduranceUnderWater = array("Swimming");
$enduranceOnEarthType = $em->getRepository('KsActivityBundle:SportType')->findOneByLabel("endurance");
if (!is_object($enduranceOnEarthType) ) {
echo "Impossible de trouver le type de sport d'endurance";
}
$enduranceUnderWaterType = $em->getRepository('KsActivityBundle:SportType')->findOneByLabel("endurance_under_water");
if (!is_object($enduranceUnderWaterType) ) {
echo "Impossible de trouver le type de sport d'endurance sous l'eau ";
}
echo "Après avoir récupéré 25 activités : ".memory_get_usage()."\n";
$a = 0;
for($i=0;$i<=$nbPages;$i++){
if($i!=0){
$activities = $rkApi->getFitnessActivities($i,25);
$aActivities = $activities->items;
}
foreach ($aActivities as $activity) {
$a = $a+1;
$codeSport = $this->formatNameSport($activity->type);
$sport = $em->getRepository('KsActivityBundle:Sport')->findOneByCodeSport($codeSport);
if (!is_object($sport) ) {
$sport = new \Ks\ActivityBundle\Entity\Sport();
$sport->setLabel($codeSport);
$sport->setCodeSport($codeSport);
$sport->setSportType($enduranceOnEarthType);
$em->persist($sport);
$em->flush();
}
$activityDetail = json_decode($rkApi->requestJSONHealthGraph($activity->uri));
if(in_array($activity->type, $aEndurance)){
$urlActivitieDetail = $activityDetail->activity;
$ActivitySessionEnduranceOnEarth = new \Ks\ActivityBundle\Entity\ActivitySessionEnduranceOnEarth($user);
isset($activity->total_distance)? $ActivitySessionEnduranceOnEarth->setDistance($activity->total_distance) : "";
isset($activity->duration)? $ActivitySessionEnduranceOnEarth->setDuration($this->secondesToTimeDuration($activity->duration)) : "";
isset($activity->start_time)? $ActivitySessionEnduranceOnEarth->setIssuedAt(new \DateTime($activity->start_time)) : "";
$ActivitySessionEnduranceOnEarth->setModifiedAt(new \DateTime('Now'));
$ActivitySessionEnduranceOnEarth->setSport($sport);
isset($activityDetail->total_calories)? $ActivitySessionEnduranceOnEarth->setCalories($activityDetail->total_calories) : "";
isset($activityDetail->climb)? $ActivitySessionEnduranceOnEarth->setElevationGain($activityDetail->climb) : "";
$maxElevation = 0;
$minElevation = 10000;
if(isset($activityDetail->path)){
foreach($activityDetail->path as $gpsPoint){
if($gpsPoint->altitude > $maxElevation){
$maxElevation = $gpsPoint->altitude;
}
if($gpsPoint->altitude < $minElevation){
$minElevation = $gpsPoint->altitude;
}
}
$ActivitySessionEnduranceOnEarth->setElevationMin($minElevation);
$ActivitySessionEnduranceOnEarth->setElevationMax($maxElevation);
}
$em->persist($ActivitySessionEnduranceOnEarth);
$em->flush();
//Pour chaque activité on a un identifiant relatif au service qu'on synchronise
$ActivityComeFromService = new \Ks\ActivityBundle\Entity\ActivityComeFromService();
$ActivityComeFromService->setActivity($ActivitySessionEnduranceOnEarth);
$ActivityComeFromService->setService($service);
$ActivityComeFromService->setIdWebsiteActivityService($activity->uri);
$ActivityComeFromService->setSourceDetailsActivity($rkApi->requestJSONHealthGraph($activity->uri));
$ActivityComeFromService->setTypeSource("JSON");
$em->persist($ActivityComeFromService);
$em->flush();
echo "Import de l'activite num ".$a." type :".$activity->type." effectue avec success \n";
unset($ActivitySessionEnduranceOnEarth);
unset($ActivityComeFromService);
echo "UnitOFWOrk -> ".$em->getUnitOfWork()->size()."\n";
}
if(in_array($activity->type, $aEnduranceUnderWater)){
$ActivitySessionEnduranceUnderWater = new \Ks\ActivityBundle\Entity\ActivitySessionEnduranceUnderWater($user);
isset($activity->total_distance)? $ActivitySessionEnduranceUnderWater->setDistance($activity->total_distance) : "";
isset($activity->duration)? $ActivitySessionEnduranceUnderWater->setDuration($this->secondesToTimeDuration($activity->duration)) : "";
isset($activity->start_time) && !empty($activity->start_time)? $ActivitySessionEnduranceUnderWater->setIssuedAt(new \DateTime($activity->start_time)) : "";
$ActivitySessionEnduranceUnderWater->setModifiedAt(new \DateTime('Now'));
$ActivitySessionEnduranceUnderWater->setSport($sport);
isset($activityDetail->total_calories)? $ActivitySessionEnduranceUnderWater->setCalories($activityDetail->total_calories) : "";
isset($activityDetail->notes)? $ActivitySessionEnduranceUnderWater->setDescription($activityDetail->notes) : "";
$em->persist($ActivitySessionEnduranceUnderWater);
$em->flush();
$ActivityComeFromService = new \Ks\ActivityBundle\Entity\ActivityComeFromService();
$ActivityComeFromService->setActivity($ActivitySessionEnduranceUnderWater);
$ActivityComeFromService->setService($service);
$ActivityComeFromService->setIdWebsiteActivityService($activity->uri);
$ActivityComeFromService->setSourceDetailsActivity($rkApi->requestJSONHealthGraph($activity->uri));
$ActivityComeFromService->setTypeSource("JSON");
$em->persist($ActivityComeFromService);
$em->flush();
echo "Import de l'activité num ".$a." type :".$activity->type." effectué avec succès\n";
unset($ActivitySessionEnduranceUnderWater);
unset($ActivityComeFromService);
}
echo "Après chaque activité : ".memory_get_usage()."\n";
unset($sport);
unset($activityDetail);
$em->clear();
}
}
} catch (\Exception $e) {
throw $e;
}
}
谢谢,@AdrienBrault。我已经测试过了,它确实消耗了更少的内存,但内存仍然增加。如何真正清除实体管理器?并稳定记忆?--env=prod --no-debug
答:
1赞
Besnik
7/10/2012
#1
尝试使用以下命令重置实体管理器:
$this->getContainer()->get('doctrine')->resetEntityManager();
然后:
$em = $this->getContainer()->get('doctrine')->getEntityManager();
10赞
Alexey B.
7/28/2014
#2
Symfony在开发环境中记录所有SQL查询,所以首先你需要禁用它
// disable logger
$em->getConnection()->getConfiguration()->setSQLLogger(null);
您可以在实体上使用事件侦听器,这也可能会增加内存使用量。您可以像这样禁用它们
// remove all listeners
foreach ($em->getEventManager()->getListeners() as $event => $listeners) {
foreach ($listeners as $listener) {
$em->getEventManager()->removeEventListener($event, $listener);
}
}
从代码中删除,不需要它们,因为您清除了实体管理器循环的每一步。unset
// save and clear
$em->flush();
$em->getUnitOfWork()->clear();
请记住,学说可以优化您的查询,如果您将查询分组到一个中,则可以提高性能。因此,最佳做法是对数据的某些部分执行一次。例如:flush
flush
// collect 100 entities and then save them
if (($i % 100) == 0) {
$em->flush();
$em->getUnitOfWork()->clear();
}
评论
0赞
GManz
8/4/2014
这并不完全是解决方案。但是您的解决方案将我引向了解决方案。事实证明,我正在重写的事件侦听器之一(通过重载它的类参数)正在做一些导致这种情况的事情。删除该定义(并仅手动删除该事件侦听器)解决了此问题。我会给你赏金。
0赞
Cyril CHAPON
12/13/2016
你是如何摆脱“未定义索引”的?你能为你谈到的扩展解决方案编写代码吗?
0赞
user3714751
11/18/2020
还有getUntiOfWork,而不是简单明了的调用,我得到了未定义的索引 - 有人想出一个真正的解决方案吗?
评论
php app/console command --env=prod --no-debug
unset