0
I urgently need to find some way to resolve this problem that has trapped me for over a week. Once solified, I believe I can use this medium to do other operations that my system will have.
I have two tables, a call from Client and another of Budget, that are related 1:n and n:1 respectively. It works like this: in the form Budget has a field select
listing all the Client, and which it assigns to the value
of each option
the id of each Client:
<div class="form-group">
<select name="cdg_budget_type[client_id]" class="form-control">
{% for client in clients %}
<option value="{{ client.id }}">{{ client.name }}</option>
{% endfor %}
</select>
</div>
First, I must show the entity Client:
class Client
{
private $id;
private $name;
private $phone;
private $email;
private $streetName;
private $district;
private $number;
private $city;
private $zipCode;
private $budget;
public function __toString()
{
return $this->name;
}
public function getId()
{
return $this->id;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getName()
{
return $this->name;
}
public function setPhone($phone)
{
$this->phone = $phone;
return $this;
}
public function getPhone()
{
return $this->phone;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function getEmail()
{
return $this->email;
}
public function setStreetName($streetName)
{
$this->streetName = $streetName;
return $this;
}
public function getStreetName()
{
return $this->streetName;
}
public function setDistrict($district)
{
$this->district = $district;
return $this;
}
public function getDistrict()
{
return $this->district;
}
public function setNumber($number)
{
$this->number = $number;
return $this;
}
public function getNumber()
{
return $this->number;
}
public function setCity($city)
{
$this->city = $city;
return $this;
}
public function getCity()
{
return $this->city;
}
public function setZipCode($zipCode)
{
$this->zipCode = $zipCode;
return $this;
}
public function getZipCode()
{
return $this->zipCode;
}
function setBudget($budget)
{
$this->budget = $budget;
}
function getBudget()
{
return $this->budget;
}
}
Now, the entity Budget:
class Budget
{
private $id;
private $clientId;
private $address;
private $installments;
private $checkDays;
private $dateStart;
private $dateCreated;
private $totalValue;
public function __construct()
{
$this->dateCreated = new \DateTime();
}
public function getId()
{
return $this->id;
}
public function setClientId(Client $clientId)
{
$this->clientId = $clientId;
return $this;
}
public function getClientId()
{
return $this->clientId;
}
public function setAddress($address)
{
$this->address = $address;
return $this;
}
public function getAddress()
{
return $this->address;
}
public function setInstallments($installments)
{
$this->installments = $installments;
return $this;
}
public function getInstallments()
{
return $this->installments;
}
public function setCheckDays($checkDays)
{
$this->checkDays = $checkDays;
return $this;
}
public function getCheckDays()
{
return $this->checkDays;
}
public function setDateStart($dateStart)
{
$this->dateStart = $dateStart;
return $this;
}
public function getDateStart()
{
return $this->dateStart;
}
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
return $this;
}
public function getDateCreated()
{
return $this->dateCreated;
}
public function setTotalValue($totalValue)
{
$this->totalValue = $totalValue;
return $this;
}
public function getTotalValue()
{
return $this->totalValue;
}
}
Following then with the file Client.orm.yml
, which lists all the fields it contains in this table and the relationship with Budget:
CDG\PanelBundle\Entity\Client:
type: entity
table: client
repositoryClass: CDG\PanelBundle\Entity\ClientRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
name:
type: string
length: 255
phone:
type: string
length: 255
email:
type: string
length: 255
streetName:
type: string
length: 255
column: street_name
district:
type: string
length: 255
number:
type: string
length: 255
city:
type: string
length: 255
zipCode:
type: string
length: 255
column: zip_code
oneToMany:
budget:
targetEntity: Budget
mappedBy: clientId
lifecycleCallbacks: { }
Here, the Budget.orm.yml
and its relationship with Client:
CDG\PanelBundle\Entity\Budget:
type: entity
table: budget
repositoryClass: CDG\PanelBundle\Entity\BudgetRepository
id:
id:
type: integer
id: true
generator:
strategy: AUTO
fields:
address:
type: string
length: 255
installments:
type: integer
checkDays:
type: integer
column: check_days
dateStart:
type: datetime
column: date_start
dateCreated:
type: datetime
column: date_created
totalValue:
type: decimal
column: total_value
nullable: true
manyToOne:
clientId:
targetEntity: Client
inversedBy: budget
joinColumn:
name: client_id
referencedColumnName: id
lifecycleCallbacks: { }
So far I believe everything is fine, but now the problem begins. It is necessary to UPDATE the field budget of Client previously selected in the form as soon as a new Budget is inserted in the database.
In my BudgetController.php
, the function addAction()
is this way below, and produces the following error:
Warning: spl_object_hash() expects Parameter 1 to be Object, array Given
public function addAction(Request $request)
{
$form = $this->createForm(new BudgetType());
$manager = $this->getDoctrine()->getManager();
$Client = $manager->getRepository('PanelBundle:Client');
$Budget = $manager->getRepository('PanelBundle:Budget');
if ($request->getMethod() == 'POST') {
$form->handleRequest($request);
if ($form->isValid()) {
$manager->persist($form->getData());
$manager->flush();
$ClientEntity = $manager->find('PanelBundle:Client', $form['client_id']->getData()->getId());
$ClientEntity->setBudget($manager->getRepository('PanelBundle:Budget')->getLastId());
$manager->persist($ClientEntity);
$manager->flush();
$this->addFlash('success', 'Novo orçamento adicionado');
return $this->redirect($this->generateUrl('panel_budgets'));
}
}
return $this->render('PanelBundle:Budget:add.html.twig', array(
'clients' => $Client->findAll(),
'form' => $form->createView()
));
}
Just to explain, the function getLastId()
that appears above returns the ID of the last Budget added:
public function getLastId()
{
return $this->createQueryBuilder('b')
->select('b.id')
->getQuery()
->getResult();
}
Describing the function quickly, it adds the data to the table budget and then, in the next part, I need to retrieve this Client selected and modify your budget. The problem is that the entity has the method __toString()
that returns the name, which is displayed on the system home page, so no object will be returned and do not know how to do. In other attempts I got an error saying it is not possible to call the method setBudget()
null.
Looking for other means, I worked out a role in the BudgetRepository.php
which have two parameters to provide the id of Client to be updated and the id of Budget which was newly included in the bank, which produces the error:
[Semantical Error] line 0, col 34 near 'budget = ? 1 WHERE': Error: Invalid Pathexpression. Statefieldpathexpression or Singlevaluedassociationfield expected.
public function addBudgetToClient($clientId, $budgetId)
{
$query = $this->createQueryBuilder('b');
$query->update('PanelBundle:Client', 'c')
->set('c.budget', '?1')
->where($query->expr()->eq('c.id', '?2'))
->setParameter(1, $budgetId)
->setParameter(2, $clientId)
->getQuery()
->execute();
}
In the addAction()
, I just inserted between the first flush()
and setFlash()
the following code snippet:
$Budget->addBudgetToClient($form['client_id']->getData()->getId(), $Budget->getLastId());
I appreciate any help, because it’s already a week on top of a problem.
ISSUE #1
On request, the BudgetType.php
:
<?php
namespace CDG\PanelBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class BudgetType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('client_id', 'entity', array(
'class' => 'PanelBundle:Client',
'attr' => array(
'class' => 'form-control'
)
))
->add('address', 'text', array(
'attr' => array(
'class' => 'form-control'
)
))
->add('installments', 'choice', array(
'choices' => array(
'3' => '3x',
'4' => '4x'
),
'attr' => array(
'class' => 'form-control',
)
))
->add('check_days', 'choice', array(
'choices' => array(
'30' => '30 dias',
'60' => '60 dias'
),
'attr' => array(
'class' => 'form-control',
)
))
->add('date_start', 'date', array(
'attr' => array(
'format' => 'yyyy-MM-dd'
)
))
->add('total_value', 'money', array(
'attr' => array(
'class' => 'form-control',
)
));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'CDG\PanelBundle\Entity\Budget',
'csrf_protection' => false,
));
}
public function getName()
{
return 'cdg_budget_type';
}
public function serialize()
{
return serialize(array(
'id' => $this->getId()
));
}
public function unserialize($serialized)
{
$data = unserialize($serialized);
$this->id = $data['id'];
}
}
Based on an example, I wrote the addAction()
in another way, but this time the error occurs below, which is strange because my Client actually in its __construct()
gives a new ArrayCollection()
in budget, but even removing, the error persists.
Catchable Fatal Error: Argument 1 passed to Doctrine Common Collections Arraycollection::__Construct() must be of the type array, Object Given, called in /home/Gabriel/Documents/Casadogesso/vendor/Doctrine/Orm/lib/Doctrine/ORM/Unitofwork.php on line 555 and defined
public function addAction(Request $request)
{
$Budget = new \CDG\PanelBundle\Entity\Budget();
$form = $this->createForm(new BudgetType(), $Budget);
$manager = $this->getDoctrine()->getManager();
if ($request->getMethod() == 'POST') {
$form->handleRequest($request);
if ($form->isValid()) {
$manager->persist($Budget);
$manager->flush();
$Client = $manager->find('CDG\PanelBundle\Entity\Client', $form['client_id']->getData()->getId());
$Client->setBudget($Budget);
$manager->persist($Client);
$manager->flush(); // Stack Trace marca aqui.
$this->addFlash('success', 'Novo orçamento adicionado');
return $this->redirect($this->generateUrl('panel_budgets'));
}
}
return $this->render('PanelBundle:Budget:add.html.twig', array(
'clients' => $manager->getRepository('PanelBundle:Client')->findAll(),
'form' => $form->createView()
));
}
ISSUE #2
Below the list of tables Client and Budget, as requested. The primary key of the Client and Budget is the field id, and in the Budget, the foreign key is client, which will store the ID of the client that budget belongs to. Please ignore "[1.]" and "" to the right side of the fields, I tried to make cardinality using Astah. :-)
You can post the code of
BudgetType
, please?– Rodrigo Rigotti
@Rodrigorigotti Oh, hello! I updated the question along with another way I wrote the
addAction()
. Thank you for your interest, I hope that with all these details it becomes clearer. :-)– fermoga