I want save purchase order header with purchase order details.This my PurchaseOrder Entity Class=>
namespace AppBundle\Entity;
use AppBundle\Entity\PurchaseInvoiceDetail;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* PurchaseOrder
*
* #ORM\Table(name="purchase_order", indexes={#ORM\Index(name="fk_purchase_order_supplier1_idx", columns={"supplier_id"})})
* #ORM\Entity
*/
class PurchaseOrder
{
/**
* #var PurchaseOrderDetails
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\PurchaseOrderDetails", mappedBy="purchaseOrder",cascade={"cascade"})
* #JMS\Type("ArrayCollection<FinanceBundle\Entity\AutoAllocation>")
*/
private $purchaseOrderDetails;
public function __construct()
{
$this->purchaseOrderDetails = new ArrayCollection();
}
public function addPurchaseOrderDetail(PurchaseOrderDetails $purchaseOrderDetails)
{
$this->purchaseOrderDetails->add($purchaseOrderDetails);
}
/**
* #return PurchaseOrderDetails
*/
public function getPurchaseOrderDetails()
{
return $this->purchaseOrderDetails;
}
/**
* #param PurchaseOrderDetails $purchaseOrderDetails
*/
public function setPurchaseOrderDetails($purchaseOrderDetails)
{
$this->purchaseOrderDetails = $purchaseOrderDetails;
}
}
and PurchaseOrderDetail class as this =>
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* PurchaseOrderDetails
*
* #ORM\Table(name="purchase_order_details", indexes={#ORM\Index(name="fk_purchase_order_details_purchase_order1_idx", columns={"purchase_order_id"}), #ORM\Index(name="fk_purchase_order_details_invt_item1_idx", columns={"id_item"})})
* #ORM\Entity
*/
class PurchaseOrderDetails
{
/**
* #var \AppBundle\Entity\PurchaseOrder
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\PurchaseOrder",inversedBy="purchaseOrderDetails")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="purchase_order_id", referencedColumnName="id")
* })
*/
private $purchaseOrder;
/**
* Set purchaseOrder
*
* #param \AppBundle\Entity\PurchaseOrder $purchaseOrder
*
* #return PurchaseOrderDetails
*/
public function setPurchaseOrder(\AppBundle\Entity\PurchaseOrder $purchaseOrder = null)
{
$this->purchaseOrder = $purchaseOrder;
return $this;
}
/**
* Get purchaseOrder
*
* #return \AppBundle\Entity\PurchaseOrder
*/
public function getPurchaseOrder()
{
return $this->purchaseOrder;
}
}
my php code in symfony 3.1 as follows=>
$em = $this->getDoctrine()->getManager();
$purchaseOrder = new PurchaseOrder();
$puchaseOrderDetail = new PurchaseOrderDetails();
$puchaseOrderDetail->setPrice(100);
$purchaseOrder->setPurchaseOrderDetails($puchaseOrderDetail);
$puchaseOrderDetail->setPurchaseOrder($purchaseOrder);
$em->persist($purchaseOrder);
$em->flush();
no errors occurred and just only purchase order have persisted and purchase order detail doesn't
You are not persisting the detail object. Either persist it manually with
$em->persist($purchaseOrderDetail);
or fix
cascade={"persist"}
in the #ORM\OneToMany annotation of PurchaseOrder::$purchaseOrderDetails (cascade={"cascade"} is probably a typo).
You need to persist PurchaseOrderDetails as well.
The below code should save both of your entities.
$em = $this->getDoctrine()->getManager();
$purchaseOrder = new PurchaseOrder();
$puchaseOrderDetail = new PurchaseOrderDetails();
$puchaseOrderDetail->setPrice(100);
$purchaseOrder->setPurchaseOrderDetails($puchaseOrderDetail);
$puchaseOrderDetail->setPurchaseOrder($purchaseOrder);
$em->persist($purchaseOrder);
$em->persist($puchaseOrderDetail);
$em->flush();
As #Finwe has mentioned, If your business logic requires, and you don't want to persist separately PurchaseOrderDetails entity while creating a new PurchaseOrder. You might consider configuring cascade_persist. which will persist automatically associated entity.
To do so, add cascade option to your association config :
#ORM\OneToMany(targetEntity="AppBundle\Entity\PurchaseOrderDetails", mappedBy="purchaseOrder",cascade={"persist"})
Related
I'm trying to get working 4 entities in Symfony 3 with Doctrine 2 but I'm stuck on a circular reference exception when I want to serialize an Account entity for example:
A circular reference has been detected (configured limit: 1).
I chose bi-directional relations in my entities and schema is like this:
- Account [1] ---- [0..*] AccountSheet
- AccountSheet [1] ---- [0..*] Operation
- Operation [0..*] ---- [1] Category
Here are entities (with some cleanings for clarity):
src\AppBundle\Entity\Account.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;
/**
* #ORM\Entity()
* #ORM\Table(name="accounts",
* uniqueConstraints={#ORM\UniqueConstraint(name="accounts_name_unique",columns={"name"})})
*/
class Account extends AbstractGenericEntity{
/**
* #ORM\OneToMany(targetEntity="AccountSheet", mappedBy="account")
* #var AccountSheet[]
*/
protected $accountSheets;
public function __construct($name = null, $description = null){
$this->accountSheets = new ArrayCollection();
$this->name = $name;
$this->description = $description;
}
}
src\AppBundle\Entity\AccountSheet.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;
/**
* #ORM\Entity()
* #ORM\Table(name="accounts_sheets",
* uniqueConstraints={#ORM\UniqueConstraint(name="accountsheet_account_unique", columns={"name", "account_id"})})
* #ORM\HasLifecycleCallbacks
*/
class AccountSheet extends AbstractGenericEntity{
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Account", inversedBy="accountSheets")
* #var Account
*/
protected $account;
/**
* #ORM\OneToMany(targetEntity="Operation", mappedBy="accountSheet")
* #var Operation[]
*/
protected $operations;
public function __construct($name = null){
$this->operations = new ArrayCollection();
$this->name = $name;
}
}
src\AppBundle\Entity\Operation.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\AbstractGenericEntity;
/**
* #ORM\Entity()
* #ORM\Table(name="operations")
*/
class Operation extends AbstractGenericEntity{
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\AccountSheet", inversedBy="operations")
* #ORM\JoinColumn(nullable=false)
* #var AccountSheet
*/
protected $accountSheet;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="operations")
* #var Category
*/
protected $category;
public function __construct($type = null, $label = null, $montant = null, $comment = null){
$this->label = $label;
$this->type = $type;
$this->comment = $comment;
$this->montant = $montant;
}
}
src\AppBundle\Entity\Category.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;
/**
* #ORM\Entity()
* #ORM\Table(name="categories")
*/
class Category extends AbstractGenericEntity{
/**
* #ORM\Column(type="string")
*/
protected $label;
/**
* #ORM\Column(type="string")
*/
protected $description;
/**
* #ORM\OneToMany(targetEntity="Operation", mappedBy="category")
* #var Operation[]
*/
protected $operations;
public function __construct($name = null){
$this->operations = new ArrayCollection();
$this->name = $name;
}
}
I guess it's on the Operation entity, where AccountSheet is referenced again. The bi-directional on operation is not really needed.
How could I rearrange this?
Thanks!
From the official documentation :
Circular references are common when dealing with entity relations
To avoid infinite loops, GetSetMethodNormalizer throws a CircularReferenceException when such a case is encountered:
$member = new Member();
$member->setName('Kévin');
$org = new Organization();
$org->setName('Les-Tilleuls.coop');
$org->setMembers(array($member));
$member->setOrganization($org);
echo $serializer->serialize($org, 'json'); // Throws a CircularReferenceException
So, from this point, you have 3 solutions to get rid of this issue :
Set a circular reference handler :
Instead of throwing an exception, circular references can also be handled by custom callables. This is especially useful when serializing entities having unique identifiers:
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer();
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getName();
});
$serializer = new Serializer(array($normalizer), array($encoder));
var_dump($serializer->serialize($org, 'json'));
// {"name":"Les-Tilleuls.coop","members":[{"name":"K\u00e9vin", organization: "Les-Tilleuls.coop"}]}
Set ignored attributes (not my preferred solution) :
in your case :
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer();
normalizer->setIgnoredAttributes(array("account", "accountSheet", "category", "operation"));
$serializer = new Serializer(array($normalizer), array($encoder));
var_dump($serializer->serialize($org, 'json'));
Use group attributes (my preferred solution) :
This method is similar to setting ignored attributes because you will chose which attribute you want to serialize by adding the group annotation on it and the rest will be ignored for recursivity during normalization process.
Using Serialization Groups Annotations
Attributes Groups
In your case with the Account entity for example do this on the account side :
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* #ORM\Entity()
* #ORM\Table(name="accounts",
* uniqueConstraints={#ORM\UniqueConstraint(name="accounts_name_unique",columns={"name"})})
*/
class Account extends AbstractGenericEntity{
/**
* #ORM\OneToMany(targetEntity="AccountSheet", mappedBy="account")
* #var AccountSheet[]
* #Groups({"account"})
*/
protected $accountSheets;
public function __construct($name = null, $description = null){
$this->accountSheets = new ArrayCollection();
$this->name = $name;
$this->description = $description;
}
}
Then do not put this group annotation on the $account field in the AccountSheet entity to get rid of the circular reference issue.
Finally you serialize your Account :
$encoder = new JsonEncoder();
$normalizer = new ObjectNormalizer();
$serializer = new Serializer(array($normalizer), array($encoder));
var_dump($serializer->serialize($account, 'json', array('groups' => array('account')) ));
$jsonContent = $serializer->serialize($yourObject, 'json', [
'circular_reference_handler' => function ($object) {
return $object->getId();
}
]);
Above code works for me to fix circular reference exception. (Symfony >=4.2)
I'm learning how to work with Neo4j and Doctrine OGM, and I'm having problems with my source code. I don't know how to use manytomany because I'm just starting learn. When I save I see:
Catchable fatal error: Argument 1 passed to Entity\Empresas::setTelefone() must be an instance of Entity\Entity\Telefones, string given, called in /Applications/MAMP/htdocs/neo4j/n4j/save.php on line 17 and defined in /Applications/MAMP/htdocs/neo4j/n4j/Empresas.php on line 50
My Empresas.php entity
namespace Entity;
use HireVoice\Neo4j\Annotation as OGM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* All entity classes must be declared as such.
*
* #OGM\Entity(labels="Empresas")
*/
class Empresas
{
/**
* The internal node ID from Neo4j must be stored. Thus an Auto field is required
* #OGM\Auto
*/
protected $id;
/**
* #OGM\Property
* #OGM\Index
*/
protected $nome;
/**
* #OGM\Property
*/
protected $keywords;
/**
* #OGM\ManyToOne(relation="tem_telefone")
*/
protected $telefone;
function getID(){
return $this->id;
}
function setNome($nome){
$this->nome = $nome;
}
function setKeywords($keywords){
$this->keywords = $keywords;
}
public function getTelefone() {
return $this->telefone;
}
public function setTelefone(Entity\Telefones $telefone) {
$this->telefone = $telefone;
}
}`
My Telefones.php Entity
<?php
namespace Entity;
use HireVoice\Neo4j\Annotation as OGM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* All entity classes must be declared as such.
*
* #OGM\Entity(labels="Empresas")
*/
class Telefones
{
/**
* The internal node ID from Neo4j must be stored. Thus an Auto field is required
* #OGM\Auto
*/
protected $id;
/**
* #OGM\Property
* #OGM\Index
*/
protected $telefone;
function getID(){
return $this->id;
}
}
And my Save.php Entity
<?php
require 'bootstrap.php';
require 'Empresas.php';
require 'Telefones.php';
$repo = $em->getRepository('Entity\\Empresas');
$empresa_container = $em->find('Entity\\Empresas', "22");
$telefones = new Entity\Telefones();
$empresa = new Entity\Empresas;
$empresa->setNome("nome");
$empresa->setKeywords("keywords");
$empresa->setTelefone("telefone");
$em->persist($telefones);
$em->persist($empresa);
$em->flush();
echo $empresa->getId();
Error
I have this two tables (see pics below) mapped as follow:
class Brand
{
...
/**
* #var Company
*
* #ORM\ManyToOne(targetEntity="Company")
* #ORM\JoinColumn(name="companies_id", referencedColumnName="id")
*/
protected $company;
}
class Company
{
...
}
I need to add support for add a new Brand from Company but I have not idea in how to achieve this. This are handled through SonataAdminBundle but I think I need to add something else to entities in order to create brands from company but I am not sure what this would be, can I get some help? I am stucked
1st attempt
After get an answer this is how I modify Company entity:
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
class Company
{
...
/**
* #var Brand
* #ORM\OneToMany(targetEntity="Brand", mappedBy="company", cascade={"persist"})
**/
protected $brands;
public function __construct()
{
$this->brands = new ArrayCollection();
}
...
public function getBrands()
{
return $this->brands;
}
/**
* Add brands
*
* #param Brand $brand
* #return Brands
*/
public function addBrand( Brand $brand)
{
$this->brands[] = $brand;
return $this;
}
/**
* Remove brands
*
* #param Brand $brand
*/
public function removeBrand( Brand $brand)
{
$this->brands->removeElement($brand);
}
}
But I am getting this error:
No entity manager defined for class
Doctrine\Common\Collections\ArrayCollection
Why is that?
You could try setting up your entities like this:
class Brand
{
/**
* #var Company
*
* #ORM\ManyToOne(targetEntity="Company", inversedBy="brands")
* #ORM\JoinColumn(name="companies_id", referencedColumnName="id")
*/
protected $company;
}
class Company
{
/**
* #var ArrayCollection
*
* #OneToMany(targetEntity="Brand", mappedBy="company", cascade={"persist"})
**/
protected $brands;
}
What we're defining here is that new Brands can be created from the Company entity with cascade={"persist"}.
It's recommended you implement addBrand and removeBrand in Company for direct interaction with the ArrayCollection.
A simple example of the final functionality:
$company = $service->getCompany(1); // our company entity
$brand = new Brand();
$brand->set...
...
$company->addBrand($brand);
$entityManager->persist($company);
EDIT
This is just an example, you may choose not to add with keys or even implement a remove function, but this is a starting point:
public function addBrand(Brand $brand)
{
// key needs to be something that can uniquely identify the brand
// e.g. name
$this->getBrands()->set(*key*, $brand);
return $this;
}
public function removeBrand($key)
{
$this->getBrands()->remove($key);
return $this;
}
I have this User entity
/**
* User Entity.
*
* #ORM\Entity
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Application\Repository\UserRepository")
* #ORM\HasLifecycleCallbacks()
* #ORM\EntityListeners({"Application\Listener\User"})
*/
class User extends Entity implements UserInterface, ProviderInterface
{
...
/**
* #var \Application\Entity\Organization
*
* #ORM\ManyToOne(targetEntity="Application\Entity\Organization")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="organization_id", referencedColumnName="organization_id")
* })
*/
protected $organization;
...
}
Wich uses the listener
namespace Application\Listener;
use Doctrine\ORM\Event\PreUpdateEventArgs;
class User
{
public function preUpdate(\Application\Entity\User $user, PreUpdateEventArgs $eventArgs)
{
if ($eventArgs->hasChangedField('organization')) {
$oldOrganization = $eventArgs->getOldValue('organization');
if ($oldOrganization) {
$oldOrganization->decreaseTotalMembers();
$eventArgs->getEntityManager()->persist($oldOrganization);
}
$newOrganization = $eventArgs->getNewValue('organization');
if ($newOrganization) {
$newOrganization->increaseTotalMembers();
$eventArgs->getEntityManager()->persist($newOrganization);
}
}
}
}
So, as you can see, every single time a user change organization, I would like to decrease the number of members in the old organization and increase in the new organization.
So, in the controller when I create an organization I have:
public function createAction(){
...
$this->getOrganizationService()->hydrateOrganization($organization, $data);
$user = $organization->getAuthor();
if (!$user->hasOrganization()) {
$user->setOrganization($organization);
$this->getUserService()->saveUser($user);
}
...
}
So I expect that when save the user (persist + flush), the increasement in the total members of the organization is flushed as well but it does not occur.
Do you have any idea on why is it happending and how to solve it?
I'm working on a form with 3 entities :
order (idorder)
support reference table (idsupport)
link table (idorder, idsupport)
And when i try to select one or more support i got this error:
Catchable Fatal Error: Argument 1 passed to Myapp\MyBundle\Entity\PcastCmdsupports::setIdsupports() must be an instance of Myapp\MyBundle\Entity\PcastSupports, instance of Doctrine\Common\Collections\ArrayCollection given,
called in C:\wamp\www\php\Symfony\vendor\symfony\src\Symfony\Component\Form\Util\PropertyPath.php on line 347 and defined in C:\wamp\www\php\Symfony\src\Myapp\MyBundle\Entity\PcastCmdsupports.php line 62
Since i already created my link table i saw on the web that i can simply create 2 Many-To-One relation in my link table :
/**
* #var PcastSupports
*
* #ORM\ManyToOne(targetEntity="PcastSupports")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="IDSUPPORTS", referencedColumnName="IDSUPPORTS")
* })
*/
private $idsupports;
/**
* #var PcastOrder
*
* #ORM\ManyToOne(targetEntity="PcastOrder")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="IDORDER", referencedColumnName="IDORDER")
* })
*/
private $idorder;
and my setters and getters :
/**
* Set idsupports
*
*/
public function setIdsupports(\Myapp\MyBundle\Entity\PcastSupports $idsupports)
{
$this->idsupports = $idsupports;
}
/**
* Get idsupports
*
*/
public function getIdsupports()
{
return $this->idsupports;
}
/**
* Set idorder
*
*/
public function setIdcommande(\Myapp\MyBundle\Entity\PcastOrder $idorder)
{
$this->idorder = $idorder;
}
/**
* Get idorder
*
*/
public function getIdorder()
{
return $this->idorder;
}
In my order form i can choose one or many supports so i created my form like this:
$form_clips = $this->createFormBuilder($cmdclips)
->add('idorder', new CmdsupportsType)
->getForm();
And finally my supportsType form:
$builder
->add('idsupports', 'entity', array(
'class' => 'MyappMyBundle:PcastSupports',
'property' => 'name',
'expanded' => true,
'multiple' => true,
'query_builder' => function(EntityRepository $er)
{
return $er->createQueryBuilder('pts')
->orderBy('pts.idsupports','ASC');
},
));
I'm not using any arraycollection so i don't understand the issue. And the issue happened during this action:
$form_clips->bindRequest($request);
Thank a lot for your help !
I tried to make it work with the many-to-many relation in a simple case (user, company and a user_company entities) but i got a problem when i try to add a company to a user:
Warning: oci_bind_by_name() [<a href='function.oci-bind-by-name'>function.oci-bind-by-name</a>]: Invalid variable used for bind in C:\wamp\www\php\Promocast\Symfony\vendor\doctrine-dbal\lib\Doctrine\DBAL\Driver\OCI8\OCI8Statement.php line 113
I googling a lot but i didn't find anything on this error... According to stack trace the error is when doctrine try to add the company object :
array('column' => ':param10', 'variable' => object(PcastCompany), 'type' => '1')
My user entity (societe = company):
/**
* #ORM\ManyToMany(targetEntity="PcastSociete", inversedBy="users")
* #ORM\JoinTable(name="PcastLienusersociete",
* joinColumns={#ORM\JoinColumn(name="ImUser_iduser", referencedColumnName="iduser")},
* inverseJoinColumns={#ORM\JoinColumn(name="PcastLienusersociete_idsociete", referencedColumnName="idsociete")}
* )
*/
private $societes;
public function getSocietes()
{
return $this->societes;
}
public function addSociete(\Myapp\MyBundle\Entity\PcastSociete $societe)
{
$this->societes[] = $societe;
}
My company entity:
/**
* #ORM\ManyToMany(targetEntity="ImUser", mappedBy="societes")
*/
private $users;
public function __construct() {
$this->users = new \Doctrine\Common\Collections\ArrayCollection();
}
If anybody have any idea...
Thanks
You should not have an entity representing the link table. If you annotate both your entities correctly, Doctrine will handle the creation of the link table by itself.
Moreover, you do not need any link table to do a Many-to-One relationship in the first place, what you want to do is use the Many-to-Many annotations in both entities.
http://readthedocs.org/docs/doctrine-orm/en/latest/reference/association-mapping.html?highlight=many%20to%20one#many-to-many-bidirectional
Start with the basics. I was curious about something else concerning ManyToMany so I grabbed your entities as a test case. Before diving into forms and such, make sure you can execute a simple test case from the command line such as:
use Zayso\ArbiterBundle\Entity\PcastSociete as Company;
use Zayso\ArbiterBundle\Entity\ImUser as User;
protected function test1()
{
$em = $this->getContainer()->get('doctrine.orm.entity_manager');
$company = new Company();
$em->persist($company);
$user = new User();
$user->addSociete($company);
$em->persist($user);
$em->flush();
}
For entities I used:
namespace Zayso\ArbiterBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class ImUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer",name="iduser")
* #ORM\GeneratedValue
*/
protected $id;
public function getId() { return $this->id; }
/**
* #ORM\ManyToMany(targetEntity="PcastSociete", inversedBy="users")
* #ORM\JoinTable(name="PcastLienusersociete",
* joinColumns={#ORM\JoinColumn(name="ImUser_iduser", referencedColumnName="iduser")},
* inverseJoinColumns={#ORM\JoinColumn(name="PcastLienusersociete_idsociete", referencedColumnName="idsociete")}
* )
*/
private $societes;
public function getSocietes()
{
return $this->societes;
}
public function addSociete(PcastSociete $societe)
{
$this->societes[] = $societe;
}
public function __construct()
{
$this->societes = new ArrayCollection();
}
}
namespace Zayso\ArbiterBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class PcastSociete
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="idsociete")
* #ORM\GeneratedValue
*/
protected $id;
public function getId() { return $this->id; }
/**
* #ORM\ManyToMany(targetEntity="ImUser", mappedBy="societes")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
}
Get the above working then we can move on to the forms problem.