Symfony3 Doctrine2无法访问循环中的变量

时间:2016-06-04 16:36:21

标签: php doctrine-orm symfony

环境

我正在使用:

  • Symfony v3.1.0;
  • Doctrine v2.5.4

问题

我从XML文件导入数据。导入工作正常,但我有更新问题。

我无法在循环中获得正确的day_id

$newest_day_id = $this->getNewestDayId();
...
->setParameter(7, $newest_day_id)

提供比实际ID小1的ID

如果我尝试:

$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)

我在数据库的NULL字段中获得day_id

CODE

这是我的控制器:

<?php

namespace AppBundle\Controller;

use \DateTime;
use AppBundle\Entity\Day;
use AppBundle\Entity\Item;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\DomCrawler\Crawler;

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;
    }
}

我的ITEM实体:

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\Table(name="item")
 */
class Item
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name_lv;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name_ru;

    /**
     * @ORM\Column(type="string", length=200)
     */
    protected $category;

    /**
     * @ORM\Column(type="string", length=500)
     */
    protected $category_full;

    /**
     * @ORM\Column(type="string", length=500)
     */
    protected $link_lv;

    /**
     * @ORM\Column(type="string", length=500)
     */
    protected $link_ru;

    /**
     * @ORM\Column(type="string", length=500)
     */
    protected $local_image_small_url;

    /**
     * @ORM\Column(type="string", length=500)
     */
    protected $local_image_big_url;

    /**
     * @ORM\Column(type="string", length=3000)
     */
    protected $description_lv;

    /**
     * @ORM\Column(type="string", length=3000)
     */
    protected $description_ru;

    /**
     * @ORM\Column(type="decimal", scale=2)
     */
    protected $price;

    /**
     * @ORM\Column(type="integer")
     */
    protected $in_stock;

    /**
     * @ORM\ManyToOne(targetEntity="Day", inversedBy="items")
     * @ORM\JoinColumn(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 \AppBundle\Entity\Day $day
     *
     * @return Item
     */
    public function setDay(\AppBundle\Entity\Day $day = null)
    {
        $this->day = $day;

        return $this;
    }

    /**
     * Get day
     *
     * @return \AppBundle\Entity\Day
     */
    public function getDay()
    {
        return $this->day;
    }
}

我的DAY实体:

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\Table(name="day")
 */
class Day
{
    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="datetime", name="updated_at")
     */
    protected $updated_at;

    /**
     * @ORM\OneToMany(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 \AppBundle\Entity\item $item
     *
     * @return Day
     */
    public function addItem(item $item)
    {
        $this->items[] = $item;

        return $this;
    }

    /**
     * Remove item
     *
     * @param \AppBundle\Entity\item $item
     */
    public function removeItem(item $item)
    {
        $this->items->removeElement($item);
    }

    /**
     * Get items
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getItems()
    {
        return $this->items;
    }
}

感谢您的时间和知识。

2 个答案:

答案 0 :(得分:0)

我没有足够的声誉来评论要求提出一些事情,但我会根据我所看到的情况尝试答案......

  1. 我建议你使用Repository来完成ImportAction和UpdateAction中的大部分重复工作。如果可能,您希望保持控制器操作更薄。
  2. 我还建议您使用EntityManager进行更新。您正在执行查询而不是让Doctrine管理它。这可能会解决它。检索项目并使用NSNumber方法更新它。
  3. 我希望这有助于解决您的问题。我建议你尝试尽可能多地使用EntityManager。我注意到您正在运行一些查询,并且您很可能通过EntityManager获得所需的信息。

答案 1 :(得分:0)

我设法让它发挥作用。

  • 重要提示:我首先保存了我的DAY实体
  • 然后我从数据库中检索了最新的DAY
  • 然后继续进行
  • 此时"MYVAR[3"在数据库中返回了实际最新的记录。
  • 所以我的代码工作了......