环境
我正在使用:
- Symfony v3.1.0;
- 教义 v2.5.4
问题
我正在从XML文件导入数据。导入工作正常,但我在更新时遇到问题。
我只是无法在循环中获得适当的day_id
。
$newest_day_id = $this->getNewestDayId();
...
->setParameter(7, $newest_day_id)
给出的 ID 比实际 ID 小 1
如果我尝试:
$newest_day_id = $this->getNewestDayId();
...
->setParameter(7, $newest_day_id + 1)
它给出一个错误
An exception occurred while executing 'UPDATE item SET name_lv = ?, name_ru = ?, description_lv = ?, description_ru = ?, price = ?, in_stock = ?, day_id = ? WHERE unique_id = ?' with params ["EDIT My Product Name LV", "EDIT My Product Name RU", "EDIT", "EDIT", "999.00", "99", 34, "0361-my-product-unique-id"]:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`tevlvnews`.`item`, CONSTRAINT `FK_1F1B251E9C24126` FOREIGN KEY (`day_id`) REFERENCES `day` (`id`) ON DELETE CASCADE)
如果我尝试:
....
->setParameter(7, $day->getId)
我在数据库的day_id
字段中得到NULL
法典
这是我的控制器:
<?php
namespace AppBundleController;
use DateTime;
use AppBundleEntityDay;
use AppBundleEntityItem;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentFilesystemFilesystem;
use SymfonyComponentFilesystemExceptionIOExceptionInterface;
use SymfonyComponentDomCrawlerCrawler;
class AdminController extends Controller
{
/**
* @Route("/import", name="admin_import")
*/
public function importAction(Request $request)
{
$document = new DOMDocument();
$tev_file_path = 'http://dev.izjoko.lv/test.xml';
$document->loadXml(file_get_contents($tev_file_path));
$now_date_time = date('Y-m-d H:i:s');
$nodeList = $document->getElementsByTagName('item');
$crawler = new Crawler();
$crawler->addDocument($document);
$crawler->addNodeList($nodeList);
$xml_item_counts = $nodeList->length;
// find newest DAY record
$em = $this->getDoctrine()->getManager();
$query = $em->createQueryBuilder()
->select('d')
->from('AppBundle:Day', 'd')
->orderBy('d.updated_at', 'DESC')
->getQuery();
$db_date_time = $query->getResult();
$db_date_time_size = sizeof($db_date_time);
// setup www folder for image path
$current_env = $this->container->get('kernel')->getEnvironment();
if ($current_env == 'dev')
{
$www_dir = 'web';
}
elseif ($current_env == 'prod')
{
$www_dir = 'www';
}
$fs = new Filesystem();
$local_image_uploads_path = $this->container->getParameter('kernel.root_dir') . '/../' . $www_dir . '/uploads/';
$local_image_uploads_path = str_replace("app/../", "", $local_image_uploads_path);
// make folder uploads inside web
if (!$fs->exists($local_image_uploads_path))
{
try
{
$fs->mkdir($local_image_uploads_path);
}
catch (IOExceptionInterface $e)
{
echo "An error occurred while creating your directory at " . $e->getPath();
}
}
// if database is empty
if ($db_date_time_size == 0)
{
$day = new Day();
$day->setUpdatedAt(new DateTime($now_date_time));
for ($i = 0; $i < $xml_item_count; $i++)
{
$unique_id = $document->getElementsByTagName('unique_id')->item($i)->textContent;
$name_lv = $document->getElementsByTagName('name_lv')->item($i)->textContent;
$name_ru = $document->getElementsByTagName('name_ru')->item($i)->textContent;
$link_lv = $document->getElementsByTagName('link_lv')->item($i)->textContent;
$link_ru = $document->getElementsByTagName('link_ru')->item($i)->textContent;
$category = $document->getElementsByTagName('category')->item($i)->textContent;
$category_full = $document->getElementsByTagName('category_full')->item($i)->textContent;
$external_image_small = $document->getElementsByTagName('image_th')->item($i)->textContent;
$external_image_big = $document->getElementsByTagName('image')->item($i)->textContent;
$description_lv = $document->getElementsByTagName('description_lv')->item($i)->textContent;
$description_ru = $document->getElementsByTagName('description_ru')->item($i)->textContent;
$price = $document->getElementsByTagName('price')->item($i)->textContent;
$in_stock = $document->getElementsByTagName('in_stock')->item($i)->textContent;
// add new record to database
$item = new Item();
$item->setUniqueId($unique_id);
$item->setNameLv($name_lv);
$item->setNameRu($name_ru);
$item->setLinkLv($link_lv);
$item->setLinkRu($link_ru);
$item->setCategory($category);
$item->setCategoryFull($category_full);
/* -----------------------------------------------------
* small picture
----------------------------------------------------- */
$image_small = file_get_contents($external_image_small);
$hex_random_bytes = bin2hex(random_bytes(8));
$file_name_small = 'img_' . $hex_random_bytes . '_th.jpg';
$local_image_small_full_path = $this->container->getParameter('kernel.root_dir') . '/../' . $www_dir . '/uploads/' . $file_name_small;
$local_image_small_full_path = str_replace("app/../", "", $local_image_small_full_path);
try
{
$fs->dumpFile($local_image_small_full_path, $image_small);
}
catch (IOExceptionInterface $e)
{
echo "An error occurred while saving your image at " . $e->getPath();
}
$local_image_small_path = 'uploads/' . $file_name_small;
$item->setLocalImageSmallUrl($local_image_small_path);
/* -----------------------------------------------------
* big picture
----------------------------------------------------- */
$image_big = file_get_contents($external_image_big);
$file_name_big = 'img_' . $hex_random_bytes . '.jpg';
$local_image_big_full_path = $this->container->getParameter('kernel.root_dir') . '/../' . $www_dir . '/uploads/' . $file_name_big;
$local_image_big_full_path = str_replace("app/../", "", $local_image_big_full_path);
try
{
$fs->dumpFile($local_image_big_full_path, $image_big);
}
catch (IOExceptionInterface $e)
{
echo "An error occurred while saving your image at " . $e->getPath();
}
$local_image_big_path = 'uploads/' . $file_name_big;
$item->setLocalImageBigUrl($local_image_big_path);
$item->setDescriptionLv($description_lv);
$item->setDescriptionRu($description_ru);
$item->setPrice($price);
$item->setInStock($in_stock);
$em->persist($item);
$item->setDay($day);
}
$em->persist($day);
$em->flush();
}
return $this->render('admin/import_tev.html.twig', array('tev_file_path' => $tev_file_path, 'xml_date_time' => $now_date_time, 'xml_item_count' => $xml_item_count));
}
/**
* @Route("/update", name="admin_update")
*/
public function updateAction(Request $request)
{
$document = new DOMDocument();
$tev_file_path = 'http://dev.izjoko.lv/test.xml';
$document->loadXml(file_get_contents($tev_file_path));
$now_date_time = date('Y-m-d H:i:s');
$nodeList = $document->getElementsByTagName('item');
$crawler = new Crawler();
$crawler->addDocument($document);
$crawler->addNodeList($nodeList);
$xml_item_count = $nodeList->length;
// find newest DAY record
$em = $this->getDoctrine()->getManager();
$query = $em->createQueryBuilder()
->select('d')
->from('AppBundle:Day', 'd')
->orderBy('d.updated_at', 'DESC')
->getQuery();
$db_date_time = $query->getResult();
$db_date_time_size = sizeof($db_date_time);
// setup www folder for image path
$current_env = $this->container->get('kernel')->getEnvironment();
if ($current_env == 'dev')
{
$www_dir = 'web';
}
elseif ($current_env == 'prod')
{
$www_dir = 'www';
}
$fs = new Filesystem();
$local_image_uploads_path = $this->container->getParameter('kernel.root_dir') . '/../' . $www_dir . '/uploads/';
$local_image_uploads_path = str_replace("app/../", "", $local_image_uploads_path);
// make folder uploads inside web
if (!$fs->exists($local_image_uploads_path))
{
try
{
$fs->mkdir($local_image_uploads_path);
}
catch (IOExceptionInterface $e)
{
echo "An error occurred while creating your directory at " . $e->getPath();
}
}
$day = new Day();
$day->setUpdatedAt(new DateTime($now_date_time));
for ($i = 0; $i < $xml_item_count; $i++)
{
$unique_id = $document->getElementsByTagName('unique_id')->item($i)->textContent;
$name_lv = $document->getElementsByTagName('name_lv')->item($i)->textContent;
$name_ru = $document->getElementsByTagName('name_ru')->item($i)->textContent;
$link_lv = $document->getElementsByTagName('link_lv')->item($i)->textContent;
$link_ru = $document->getElementsByTagName('link_ru')->item($i)->textContent;
$category = $document->getElementsByTagName('category')->item($i)->textContent;
$category_full = $document->getElementsByTagName('category_full')->item($i)->textContent;
$external_image_small = $document->getElementsByTagName('image_th')->item($i)->textContent;
$external_image_big = $document->getElementsByTagName('image')->item($i)->textContent;
$description_lv = $document->getElementsByTagName('description_lv')->item($i)->textContent;
$description_ru = $document->getElementsByTagName('description_ru')->item($i)->textContent;
$price = $document->getElementsByTagName('price')->item($i)->textContent;
$in_stock = $document->getElementsByTagName('in_stock')->item($i)->textContent;
if ($this->checkIfUniqueIdRecordExistsAction($unique_id) == true)
{
// update existing record
$newest_day_id = $this->getNewestDayId();
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$q = $qb->update('AppBundle:Item', 'i')
->set('i.name_lv', '?1')
->set('i.name_ru', '?2')
->set('i.description_lv', '?3')
->set('i.description_ru', '?4')
->set('i.price', '?5')
->set('i.in_stock', '?6')
->set('i.day', '?7')
->where('i.unique_id = :unique_id')
->setParameter('unique_id', $unique_id)
->setParameter(1, $name_lv)
->setParameter(2, $name_ru)
->setParameter(3, $description_lv)
->setParameter(4, $description_ru)
->setParameter(5, $price)
->setParameter(6, $in_stock)
->setParameter(7, $newest_day_id)
->getQuery();
$q->execute();
}
elseif ($this->checkIfUniqueIdRecordExistsAction($unique_id) == false)
{
//TODO: add new data
$item = new Item();
$item->setUniqueId($unique_id);
$item->setNameLv($name_lv);
$item->setNameRu($name_ru);
$item->setLinkLv($link_lv);
$item->setLinkRu($link_ru);
$item->setCategory($category);
$item->setCategoryFull($category_full);
/* -----------------------------------------------------
* small image
----------------------------------------------------- */
$image_small = file_get_contents($external_image_small);
$hex_random_bytes = bin2hex(random_bytes(8));
$file_name_small = 'img_' . $hex_random_bytes . '_th.jpg';
$local_image_small_full_path = $this->container->getParameter('kernel.root_dir') . '/../' . $www_dir . '/uploads/' . $file_name_small;
$local_image_small_full_path = str_replace("app/../", "", $local_image_small_full_path);
try
{
$fs->dumpFile($local_image_small_full_path, $image_small);
}
catch (IOExceptionInterface $e)
{
echo "An error occurred while saving your image at " . $e->getPath();
}
$local_image_small_path = 'uploads/' . $file_name_small;
$item->setLocalImageSmallUrl($local_image_small_path);
/* -----------------------------------------------------
* big image
----------------------------------------------------- */
$image_big = file_get_contents($external_image_big);
$file_name_big = 'img_' . $hex_random_bytes . '.jpg';
$local_image_big_full_path = $this->container->getParameter('kernel.root_dir') . '/../' . $www_dir . '/uploads/' . $file_name_big;
$local_image_big_full_path = str_replace("app/../", "", $local_image_big_full_path);
try
{
$fs->dumpFile($local_image_big_full_path, $image_big);
}
catch (IOExceptionInterface $e)
{
echo "An error occurred while saving your image at " . $e->getPath();
}
$local_image_big_path = 'uploads/' . $file_name_big;
$item->setLocalImageBigUrl($local_image_big_path);
$item->setDescriptionLv($description_lv);
$item->setDescriptionRu($description_ru);
$item->setPrice($price);
$item->setInStock($in_stock);
$em->persist($item);
$item->setDay($day);
}
}
$em->persist($day);
$em->flush();
return $this->render('admin/import_tev.html.twig', array('tev_file_path' => $tev_file_path, 'xml_date_time' => $now_date_time, 'xml_item_count' => $xml_item_count));
}
private function checkIfUniqueIdRecordExistsAction($unique_id)
{
// check if record with identic unique_id is already in database
$em = $this->getDoctrine()->getManager();
$query = $em->createQueryBuilder()
->select('i')
->from('AppBundle:Item', 'i')
->where('i.unique_id = :unique_id')
->setParameter('unique_id', $unique_id)
->setMaxResults(1)
->getQuery();
$db_unique_id = $query->getResult();
$db_unique_id_size = sizeof($db_unique_id);
if ($db_unique_id_size == 0) {
// not in database
return false;
} elseif ($db_unique_id_size > 0) {
// exists in database
return true;
}
}
private function getNewestDayId()
{
// fnd newest DAY record id
$em = $this->getDoctrine()->getManager();
$query = $em->createQueryBuilder()
->select('d')
->from('AppBundle:Day', 'd')
->orderBy('d.updated_at', 'DESC')
->setMaxResults(1)
->getQuery();
$db_date_time = $query->getResult();
$db_date_time_id = $db_date_time[0]->getId();
return $db_date_time_id;
}
}
我的项目实体:
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
use SymfonyComponentValidatorConstraints as Assert;
/**
* @ORMEntity
* @ORMTable(name="item")
*/
class Item
{
/**
* @ORMColumn(type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORMColumn(type="string", length=100)
*/
protected $name_lv;
/**
* @ORMColumn(type="string", length=100)
*/
protected $name_ru;
/**
* @ORMColumn(type="string", length=200)
*/
protected $category;
/**
* @ORMColumn(type="string", length=500)
*/
protected $category_full;
/**
* @ORMColumn(type="string", length=500)
*/
protected $link_lv;
/**
* @ORMColumn(type="string", length=500)
*/
protected $link_ru;
/**
* @ORMColumn(type="string", length=500)
*/
protected $local_image_small_url;
/**
* @ORMColumn(type="string", length=500)
*/
protected $local_image_big_url;
/**
* @ORMColumn(type="string", length=3000)
*/
protected $description_lv;
/**
* @ORMColumn(type="string", length=3000)
*/
protected $description_ru;
/**
* @ORMColumn(type="decimal", scale=2)
*/
protected $price;
/**
* @ORMColumn(type="integer")
*/
protected $in_stock;
/**
* @ORMManyToOne(targetEntity="Day", inversedBy="items")
* @ORMJoinColumn(name="day_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $day;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nameLv
*
* @param string $nameLv
*
* @return Item
*/
public function setNameLv($nameLv)
{
$this->name_lv = $nameLv;
return $this;
}
/**
* Get nameLv
*
* @return string
*/
public function getNameLv()
{
return $this->name_lv;
}
/**
* Set nameRu
*
* @param string $nameRu
*
* @return Item
*/
public function setNameRu($nameRu)
{
$this->name_ru = $nameRu;
return $this;
}
/**
* Get nameRu
*
* @return string
*/
public function getNameRu()
{
return $this->name_ru;
}
/**
* Set category
*
* @param string $category
*
* @return Item
*/
public function setCategory($category)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* @return string
*/
public function getCategory()
{
return $this->category;
}
/**
* Set categoryFull
*
* @param string $categoryFull
*
* @return Item
*/
public function setCategoryFull($categoryFull)
{
$this->category_full = $categoryFull;
return $this;
}
/**
* Get categoryFull
*
* @return string
*/
public function getCategoryFull()
{
return $this->category_full;
}
/**
* Set linkLv
*
* @param string $linkLv
*
* @return Item
*/
public function setLinkLv($linkLv)
{
$this->link_lv = $linkLv;
return $this;
}
/**
* Get linkLv
*
* @return string
*/
public function getLinkLv()
{
return $this->link_lv;
}
/**
* Set linkRu
*
* @param string $linkRu
*
* @return Item
*/
public function setLinkRu($linkRu)
{
$this->link_ru = $linkRu;
return $this;
}
/**
* Get linkRu
*
* @return string
*/
public function getLinkRu()
{
return $this->link_ru;
}
/**
* Set localImageSmallUrl
*
* @param string $localImageSmallUrl
*
* @return Item
*/
public function setLocalImageSmallUrl($localImageSmallUrl)
{
$this->local_image_small_url = $localImageSmallUrl;
return $this;
}
/**
* Get localImageSmallUrl
*
* @return string
*/
public function getLocalImageSmallUrl()
{
return $this->local_image_small_url;
}
/**
* Set localImageBigUrl
*
* @param string $localImageBigUrl
*
* @return Item
*/
public function setLocalImageBigUrl($localImageBigUrl)
{
$this->local_image_big_url = $localImageBigUrl;
return $this;
}
/**
* Get localImageBigUrl
*
* @return string
*/
public function getLocalImageBigUrl()
{
return $this->local_image_big_url;
}
/**
* Set descriptionLv
*
* @param string $descriptionLv
*
* @return Item
*/
public function setDescriptionLv($descriptionLv)
{
$this->description_lv = $descriptionLv;
return $this;
}
/**
* Get descriptionLv
*
* @return string
*/
public function getDescriptionLv()
{
return $this->description_lv;
}
/**
* Set descriptionRu
*
* @param string $descriptionRu
*
* @return Item
*/
public function setDescriptionRu($descriptionRu)
{
$this->description_ru = $descriptionRu;
return $this;
}
/**
* Get descriptionRu
*
* @return string
*/
public function getDescriptionRu()
{
return $this->description_ru;
}
/**
* Set price
*
* @param string $price
*
* @return Item
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Get price
*
* @return string
*/
public function getPrice()
{
return $this->price;
}
/**
* Set inStock
*
* @param integer $inStock
*
* @return Item
*/
public function setInStock($inStock)
{
$this->in_stock = $inStock;
return $this;
}
/**
* Get inStock
*
* @return integer
*/
public function getInStock()
{
return $this->in_stock;
}
/**
* Set day
*
* @param AppBundleEntityDay $day
*
* @return Item
*/
public function setDay(AppBundleEntityDay $day = null)
{
$this->day = $day;
return $this;
}
/**
* Get day
*
* @return AppBundleEntityDay
*/
public function getDay()
{
return $this->day;
}
}
我的 DAY 实体:
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
use SymfonyComponentValidatorConstraints as Assert;
/**
* @ORMEntity
* @ORMTable(name="day")
*/
class Day
{
/**
* @ORMColumn(type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORMColumn(type="datetime", name="updated_at")
*/
protected $updated_at;
/**
* @ORMOneToMany(targetEntity="Item", mappedBy="day")
*/
protected $items;
public function __construct()
{
$this->items = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set updatedAt
*
* @param DateTime $updatedAt
*
* @return Day
*/
public function setUpdatedAt($updatedAt)
{
$this->updated_at = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* @return DateTime
*/
public function getUpdatedAt()
{
return $this->updated_at;
}
/**
* Add item
*
* @param AppBundleEntityitem $item
*
* @return Day
*/
public function addItem(item $item)
{
$this->items[] = $item;
return $this;
}
/**
* Remove item
*
* @param AppBundleEntityitem $item
*/
public function removeItem(item $item)
{
$this->items->removeElement($item);
}
/**
* Get items
*
* @return DoctrineCommonCollectionsCollection
*/
public function getItems()
{
return $this->items;
}
}
感谢您的时间和知识。
我没有足够的声誉来评论一些事情来问一些事情,但我将根据我所看到的来尝试答案......
- 我建议您使用存储库来完成ImportAction和UpdateAction中的大部分重复工作。如果可能,您希望使控制器操作更薄。
- 我还建议您使用实体管理器,即使是更新。您正在执行查询,而不是让 Doctrine 管理它。这可能会解决它。检索项目并使用
$item->set*()
方法对其进行更新。
我希望这有助于解决您的问题。我建议您尝试尽可能多地使用实体管理器。我注意到您正在运行一些查询,并且您可能可以通过 EntityManager 获得所需的内容。
我设法让它工作。
- 重要提示:我先保存了我的 DAY 实体
- 然后我从数据库中检索了最新的DAY
- 然后像以前一样继续
- 此时,
$newest_day_id = $this->getNewestDayId();
返回数据库中的实际最新记录。 - 所以我的代码工作了...