Всем доброго времени суток.
Сегодня столкнулся со следующей очень странной проблемой.
Что имеется:
PHP на Windows 7 x64, версия 5.3.17, Apache версии 2.4 (на работе 2.2), PHP подключен как модуль. Symfony версии 2.0.16, Doctrine версии 2.1.
Были созданы для теста три таблицы -
а
,
b
, и
a_b
, хранящая связи "многие-ко-многим". Были созданы тестовые сущности Doctrine MyUsers и MyComments, была сделана привязка через метаданные к этим таблицам. На этом этапе всё хорошо. Вот код, который содержится в классах сущностей:
<?php
namespace TTCom\BillingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* TTCom\BillingBundle\Entity\MyUsers
*
* @ORM\Table(name="a")
* @ORM\Entity
*/
class MyUsers
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(name="id", type="integer", nullable=false)
*/
private $id;
/**
* @var string $name
*
* @ORM\Column(name="name", type="varchar(255)", nullable=false)
*/
private $name;
/**
* Bidirectional - Many users have Many favorite comments (OWNING SIDE)
*
* @ORM\ManyToMany(targetEntity="MyComments", inversedBy="userFavorites")
* @ORM\JoinTable(name="a_b",
* joinColumns={@ORM\JoinColumn(name="a_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="b_id", referencedColumnName="id")}
* )
*/
private $favorites;
public function getName() {
return $this->name;
}
public function getFavoriteComments() {
return $this->favorites;
}
public function addFavorite(Comment $comment) {
$this->favorites->add($comment);
$comment->addUserFavorite($this);
}
public function removeFavorite(Comment $comment) {
$this->favorites->removeElement($comment);
$comment->removeUserFavorite($this);
}
}
<?php
namespace TTCom\BillingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* TTCom\BillingBundle\Entity\MyComments
*
* @ORM\Table(name="b")
* @ORM\Entity
*/
class MyComments
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(name="id", type="integer", nullable=false)
*/
private $id;
/**
* @var string $text
*
* @ORM\Column(name="text", type="varchar(255)", nullable=false)
*/
private $text;
/**
* Bidirectional - Many comments are favorited by many users (INVERSE SIDE)
*
* @ORM\ManyToMany(targetEntity="MyUsers", mappedBy="favorites")
*/
private $userFavorites;
public function getCommentText() {
return $this->text;
}
public function getUserFavorites() {
return $this->userFavorites;
}
}
Вот код, который я набросал для теста в одном из контроллеров:
public function testAction(Request $request) {
$em = $this->getDoctrine()->getEntityManager();
$user = $em->getRepository('TTComBillingBundle:MyUsers')->findOneById(1);
$fav = $user->getFavoriteComments();
//return new Response(print_r(\Doctrine\Common\Util\Debug::dump($fav[0]), true)); //1
//return new Response(count($fav)); //2
$a = array();
//count($fav); //3
//for ($i = 0; $i < count($fav); $i++) {
//print_r(\Doctrine\Common\Util\Debug::dump($fav[$i])); //4
//$a[] = $fav[$i]->getCommentText(); //5
//}
//array_walk($fav, function($el, $i) use ($a, $fav) { print_r(\Doctrine\Common\Util\Debug::dump($el)); $a[] = $fav[$i]->getCommentText(); }); //6
print_r($a);
//return new Response(print_r($f[0], true)); //7
//return new Response(print_r(\Doctrine\Common\Util\Debug::dump($user->getFavoriteComments()), true)); //8
return new Response($user->getName().": ".implode(", ", $a)); //9
$objects = $em->getRepository('TTComBillingBundle:AlarmObject')->getList();
$events = $em->getRepository('TTComBillingBundle:AlarmLogEntry')->getList();
return $this->render('TTComBillingBundle:Default:alarm.html.twig',array('objects' => $objects, 'events' => $events));
}
Что происходит в моём коде:
Под "нормально" подразумевается вывод
array(2) {
[0]=>
object(stdClass)#548 (4) {
["__CLASS__"]=>
string(37) "TTCom\BillingBundle\Entity\MyComments"
["id"]=>
int(1)
["text"]=>
string(2) "b1"
["userFavorites"]=>
string(8) "Array(2)"
}
[1]=>
object(stdClass)#540 (4) {
["__CLASS__"]=>
string(37) "TTCom\BillingBundle\Entity\MyComments"
["id"]=>
int(2)
["text"]=>
string(2) "b2"
["userFavorites"]=>
string(8) "Array(1)"
}
}
в результате вызова
print_r(\Doctrine\Common\Util\Debug::dump($el));
внутри callback-функции, а также непустой массив $a, содержащий два элемента: "b1" и "b2".
Я так понимаю, проблема в ленивой инициализации объектов. Можно ли её как-нибудь отключить? Или использование array_walk и array_map с массивами объектов Doctrine - дурной тон и этого следует избегать? Потому как вызов count($fav) или пробежка через for вхолостую до первого использования array_walk/array_filter/array_map выглядит очень грязным хаком.