Rikijs Rikijs - 6 months ago 22
PHP Question

Symfony3 Doctrine2 can not access variable in the loop

ENVIRONMENT



I am using:


  • Symfony v3.1.0;

  • Doctrine v2.5.4



PROBLEM



I am importing data from XML file. Import works fine, but I have problems with update.

I just can not get proper
day_id
in the loop.

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


gives ID that is by 1 smaller than actual id

if I try:

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


it gives an error

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)


and if I try:

....
->setParameter(7, $day->getId)


I get
NULL
in the
day_id
field in the database

CODE



here is my controller:

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


My ITEM entity:

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


My DAY entity:

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


Thank you for your time and knowledge.

Answer

I managed to make it work.

  • NOTE: I saved my DAY entity first
  • Then I retrieved newest DAY from database
  • Then proceeded as previously
  • At which point $newest_day_id = $this->getNewestDayId(); returned actually newest record in the database.
  • So my code worked...