我正试图编写一个针对MySQL DB提交的表单,但我无法使其工作,我尝试了很多事情(单独的表单,创建一个字段的->add('foo', new foo())
,尝试用普通HTML表单解析纯SQL是我唯一的解决方案,这显然不是最好的。
这是我的数据库结构:
[在此输入图像描述][1]
正如你所看到的,我需要在写ticketcomments
的用户中插入comments
文本区域,等等。
在crmentity
上的description
字段。
然后在ticketcf
上,我需要从表单提交的字段是这样的(因为你不知道我是否因为字段名而不告诉你):
tcf.cf594 AS Type,
tcf.cf675 AS Suscription,
tcf.cf770 AS ID_PRODUCT,
tcf.cf746 AS NotificationDate,
tcf.cf747 AS ResponseDate,
tcf.cf748 AS ResolutionDate,
当然,对于提交的表单,每个表都需要具有相同的ticketid
id,因此我们可以通过一个简单的查询来检索它。
使用普通SQL而不是使用DQL和Symfony2表单会很容易,但这不是一个好方法
编辑这是我新创建的实体Ticket.php
,它与上面的表有关系。。。如果有人能检查一下并告诉我是否可以。。。
ticket.php
<?php
namespace WbsGoclientsBundleEntity;
use DoctrineORMMapping as ORM;
/**
* VtigerTicketcomments
*
* @ORMTable(name="vtiger_troubletickets")
* @ORMEntity(repositoryClass="WbsGoclientsBundleEntityTicketsRepository")
*/
class Tickets
{
/**
* @var WbsGoclientsBundleEntityVtigerCrmentity
*
* @ORMOneToOne(targetEntity="WbsGoclientsBundleEntityVtigerCrmentity")
* @ORMJoinColumns({
* @ORMJoinColumn(name="ticketid", referencedColumnName="crmid", unique=true)
* })
* @ORMId
*/
private $id;
/**
* @var string
*
* @ORMColumn(name="ticket_no", type="string", length=100, nullable=false)
*
*/
private $ticketNo;
/**
* @var string
*
* @ORMColumn(name="groupname", type="string", length=100, nullable=true)
*/
private $groupName;
/**
* @ORMManyToOne(targetEntity="VtigerContactdetails")
* @ORMJoinColumns({
* @ORMJoinColumn(name="parent_id", referencedColumnName="contactid", unique=true)
* })
*/
private $parentId;
/**
* @ORMManyToOne(targetEntity="VtigerAssets")
* @ORMJoinColumns({
* @ORMJoinColumn(name="product_id", referencedColumnName="assetsid", unique=true)
* })
*/
private $productId;
/**
* @var string
*
* @ORMColumn(name="priority", type="string", length=100, nullable=true)
*/
private $priority;
/**
* @var string
*
* @ORMColumn(name="severity", type="string", length=100, nullable=true)
*/
private $severity;
/**
* @var string
*
* @ORMColumn(name="status", type="string", length=100, nullable=true)
*/
private $status;
/**
* @var string
*
* @ORMColumn(name="category", type="string", length=100, nullable=true)
*/
private $category;
/**
* @var string
*
* @ORMColumn(name="title", type="string", length=255, nullable=true)
*/
private $title;
/**
* @var text
*
* @ORMColumn(name="solution", type="text", nullable=true)
*/
private $solution;
/**
* @var text
*
* @ORMColumn(name="update_log", type="text", nullable=true)
*/
private $updateLog;
/**
* @var integer
*
* @ORMColumn(name="version_id", type="integer", nullable=true)
*/
private $versionId;
/**
* @var string
*
* @ORMColumn(name="hours", type="string", length=255, nullable=true)
*/
private $hours;
/**
* @var string
*
* @ORMColumn(name="days", type="string", length=255, nullable=true)
*/
private $days;
/**
* @var integer
*
* @ORMColumn(name="from_portal", type="integer", nullable=true)
*/
private $fromPortal;
/**
* @ORMOneToMany(targetEntity="VtigerTicketcomments", mappedBy="ticketid")
*
*/
protected $comments;
/**
* @ORMOneToOne(targetEntity="VtigerTicketcf", mappedBy="id")
*/
protected $ticketcf;
/**
* @ORMOneToOne(targetEntity="VtigerCrmentity", mappedBy="crmid")
*/
protected $crmtable;
}
VtigerTicketcf.php
<?php
namespace WbsGoclientsBundleEntity;
use DoctrineORMMapping as ORM;
/**
* VtigerTicketcf
*
* @ORMTable(name="vtiger_ticketcf")
* @ORMEntity
*/
class VtigerTicketcf
{
/**
* @var string
*
* @ORMColumn(name="cf_546", type="string", length=255, nullable=true)
*/
private $cf546;
/**
* @var string
*
* @ORMColumn(name="cf_556", type="string", length=255, nullable=true)
*/
private $cf556;
/**
* @var string
*
* @ORMColumn(name="cf_589", type="string", length=3, nullable=true)
*/
private $cf589;
/**
* @var string
*
* @ORMColumn(name="cf_590", type="string", length=3, nullable=true)
*/
private $cf590;
/**
* @var string
*
* @ORMColumn(name="cf_592", type="string", length=100, nullable=true)
*/
private $cf592;
/**
* @var string
*
* @ORMColumn(name="cf_593", type="string", length=255, nullable=true)
*/
private $cf593;
/**
* @var string
*
* @ORMColumn(name="cf_594", type="string", length=255, nullable=true)
*/
private $cf594;
/**
* @var string
*
* @ORMColumn(name="cf_675", type="string", length=50, nullable=true)
*/
private $cf675;
/**
* @var float
*
* @ORMColumn(name="cf_689", type="decimal", nullable=true)
*/
private $cf689;
/**
* @var float
*
* @ORMColumn(name="cf_690", type="decimal", nullable=true)
*/
private $cf690;
/**
* @var float
*
* @ORMColumn(name="cf_691", type="decimal", nullable=true)
*/
private $cf691;
/**
* @var float
*
* @ORMColumn(name="cf_693", type="decimal", nullable=true)
*/
private $cf693;
/**
* @var string
*
* @ORMColumn(name="cf_746", type="string", length=50, nullable=true)
*/
private $cf746;
/**
* @var string
*
* @ORMColumn(name="cf_747", type="string", length=50, nullable=true)
*/
private $cf747;
/**
* @var string
*
* @ORMColumn(name="cf_748", type="string", length=50, nullable=true)
*/
private $cf748;
/**
* @var string
*
* @ORMColumn(name="cf_761", type="string", length=255, nullable=true)
*/
private $cf761;
/**
* @var string
*
* @ORMColumn(name="cf_763", type="string", length=255, nullable=true)
*/
private $cf763;
/**
* @var string
*
* @ORMColumn(name="cf_764", type="string", length=255, nullable=true)
*/
private $cf764;
/**
* @var string
*
* @ORMColumn(name="cf_765", type="string", length=255, nullable=true)
*/
private $cf765;
/**
* @var string
*
* @ORMColumn(name="cf_770", type="string", length=50, nullable=true)
*/
private $cf770;
/**
* @var WbsGoclientsBundleEntityTickets
* @ORMId
* @ORMOneToOne(targetEntity="WbsGoclientsBundleEntityTickets")
* @ORMJoinColumns({
* @ORMJoinColumn(name="ticketid", referencedColumnName="ticketid", unique=true)
* })
*
*/
private $id;
}
VtigerTicketcomments.php
<?php
namespace WbsGoclientsBundleEntity;
use DoctrineORMMapping as ORM;
/**
* VtigerTicketcomments
*
* @ORMTable(name="vtiger_ticketcomments")
* @ORMEntity
*/
class VtigerTicketcomments
{
/**
* @var string
*
* @ORMColumn(name="comments", type="text", nullable=true)
*/
private $comments;
/**
* @var integer
*
* @ORMColumn(name="ownerid", type="integer", nullable=false)
*/
private $ownerid;
/**
* @var string
*
* @ORMColumn(name="ownertype", type="string", length=10, nullable=true)
*/
private $ownertype;
/**
* @var DateTime
*
* @ORMColumn(name="createdtime", type="datetime", nullable=false)
*/
private $createdtime;
/**
* @var integer
*
* @ORMColumn(name="commentid", type="integer")
* @ORMId
*/
private $id;
/**
* @var WbsGoclientsBundleEntityTickets
* @ORMOneToOne(targetEntity="WbsGoclientsBundleEntityTickets")
* @ORMJoinColumns({
* @ORMJoinColumn(name="ticketid", referencedColumnName="ticketid", unique=true)
* })
*
*/
private $ticketid;
}
VtigerCmentity.php
<?php
namespace WbsGoclientsBundleEntity;
use DoctrineORMMapping as ORM;
/**
* VtigerCrmentity
*
* @ORMTable(name="vtiger_crmentity")
* @ORMEntity
*/
class VtigerCrmentity
{
/**
* @var integer
*
* @ORMColumn(name="smcreatorid", type="integer", nullable=false)
*/
private $smcreatorid;
/**
* @var integer
*
* @ORMColumn(name="smownerid", type="integer", nullable=false)
*/
private $smownerid;
/**
* @var integer
*
* @ORMColumn(name="modifiedby", type="integer", nullable=false)
*/
private $modifiedby;
/**
* @var string
*
* @ORMColumn(name="setype", type="string", length=30, nullable=false)
*/
private $setype;
/**
* @var string
*
* @ORMColumn(name="description", type="text", nullable=true)
*/
private $description;
/**
* @var DateTime
*
* @ORMColumn(name="createdtime", type="datetime", nullable=false)
*/
private $createdtime;
/**
* @var DateTime
*
* @ORMColumn(name="modifiedtime", type="datetime", nullable=false)
*/
private $modifiedtime;
/**
* @var DateTime
*
* @ORMColumn(name="viewedtime", type="datetime", nullable=true)
*/
private $viewedtime;
/**
* @var string
*
* @ORMColumn(name="status", type="string", length=50, nullable=true)
*/
private $status;
/**
* @var integer
*
* @ORMColumn(name="version", type="integer", nullable=false)
*/
private $version;
/**
* @var integer
*
* @ORMColumn(name="presence", type="integer", nullable=true)
*/
private $presence;
/**
* @var integer
*
* @ORMColumn(name="deleted", type="integer", nullable=false)
*/
private $deleted;
/**
* @var integer
*
* @ORMColumn(name="crmid", type="integer")
* @ORMId
*/
private $crmid;
}
这是我的存储库方法
public function findByIdAndCustomerId($id) {
$query = $this->getEntityManager()
->createQuery(
'
SELECT
IDENTITY(t.id) AS id,
t.ticketNo AS Ticket,
t.title AS Asunto,
t.status AS Estado,
t.updateLog AS LOG,
t.hours AS Horas,
t.solution AS Solucion,
t.priority AS Prioridad,
tcf.cf748 AS F_Reso,
tcf.cf747 AS F_Resp,
tcf.cf746 AS F_Noti,
tcf.cf770 AS IDPROD,
tcf.cf594 AS Tipo,
tcf.cf675 AS Suscripcion,
c.comments AS Comments,
CONCAT (CONCAT(s.firstname, ' '), s.lastname) AS Contacto
FROM WbsGoclientsBundle:Tickets t
JOIN t.parentId s
JOIN t.ticketcf tcf
JOIN t.comments c
WHERE t.ticketNo = :ticketNo
')
->setParameter('ticketNo', $id)
;
try {
//return $query->getSingleResult();
return $query->getResult();
}
catch (DoctrineORMNoResultException $e)
{
return null;
}
}
即使我只搜索一个ID,我也可以检索到一个X票的数组,因为如果ID1有4个注释,那么我得到了4个相同的票,每个注释一个。。。如何使用comments => array(...)
使其仅为一个票证,以便在树枝内的comments
数组内进行迭代?
而且VtigerCrmentity.Description
也不工作,它返回这个错误。。。
注意:未定义的索引:crmid in/var/www/wbsgo/dev.wbsgo/vendor/doctrine/orm/lib/doctrine/orm/Query/SqlWalker.php826线
我没有getter和setter,因为我正在重新生成它们,如果注释正常,实体将使用get/set正确更新,我的表单将能够使用关系提交,对吧?
您可以通过将mapped
选项设置为false来嵌入表示底层实体字段的表单,例如:
->add('comments', 'collection', array(
'type' => new VtigerTicketcommentsType(),
'mapped' => false
))
但是,在分配表单数据时要小心,因为$form->submit($data)
不会将数据设置为注释对象的底层集合。您需要在控制器中手动处理它们。在数据提交到表单后,您可以使用$form->getExtraData()
访问标记为未映射的数据。
如果你想让Symfony自动将数据设置为注释,你需要在VtigerTroubletickets
和VtigerTicketcomments
实体之间构建一个关系,根据问题标题,你没有并试图避免这种关系。
编辑:
表单类型绑定到给定的实体类。默认情况下,添加到表单类型的每个字段都必须在声明的实体类中具有底层属性(如果属性未定义为公共,则为getter/setter对)。根据表单类型(OpenTicketType
)和数据(new VtigerTroubletickets()
)构造表单对象时:
$form = $this->createForm(new OpenTicketType(), new VtigerTroubletickets());
表单获取您刚刚创建的对象中存在的数据的边界。对象没有comments属性,更重要的是,表单本身知道字段没有映射,也不会尝试从对象中填充字段,因此集合自然会呈现为空,因为没有传递有关注释的数据。
为了克服这一点,您可以传递数据数组,而不是新创建的对象(注意:值可能为空,但注释数组的长度必须大于0-注释必须存在,尽管没有实际数据)。
[
"title" => "...",
"priority" => "...",
"solution" => "...",
"comments" => [
0 => [/* comment 0 data */],
1 => [/* comment 1 data */],
.......
]
]
这就是表单创建。当表单被POST ed时,除了构造表单之外还有一个额外的步骤。请求数据必须绑定到表单上,所以您可以执行$form->submit($request)
。现在,表单AND底层实体对象将填充新的数据。
$form->getExtraData()
只是一种访问表单所包含的数据的方法,并且没有映射到底层对象——注释字段就是底层对象,因为我们将其标记为底层对象。
除了使用getExtraData
(手动从表单中提取数据)之外,您还可以使用getters/ssetters将属性comments
添加到VtigerTroubletickets
实体中,而不将其标记为db列。这样,您可以删除表单类型中的mapped => false
选项,表单将自动读取/填充注释属性。不过,在持久化时,这些注释将不会被考虑用于存储,因此您必须手动处理它们。同样,当从数据库中获取对象时,comments属性将为空,因此在创建表单之前,您必须向对象添加一些注释,例如:
$tickets = new VtigerTroubletickets();
$tickets->setComments(....);
$form = $this->createForm(new OpenTicketType(), $tickets);
我认为@usoban已经帮了你很多忙。把这看作是两个长的评论,而不是答案。
看起来你有一个票证实体和一个注释实体,它们之间有1对多的关系,但你不想在它们之间建立正式的关系,因为"DB被另一个平台使用"?这到底意味着什么。您是否正在与另一个应用程序共享php代码?你在用教义2吗?使用条令2,您可以在不更改实际数据库的情况下建立关系。
您真的应该考虑将getComments添加到您的ticket实体中。这将使你的S2生活更加轻松。
这个答案建立在@usoban所说的使用数组的基础上,但方法略有不同。
// In the controller
$formData = array();
$formData['ticket'] = new Ticket(),
$formData['comments'] = array(new Comment(), new Comment());
$form = $this->createForm(new TicketCommentsType(), $formData);
$form->handleRequest($request);
if ($form->isValid())
{
$formData = $form->getData();
$ticket = $formData['ticket'];
$comments = $formData['comments'];
// Persist ticket
// Persist comments
TicketCommentsFormType只是将两个不同的实体合并为一个表单。
class TicketCommentsFormType
public function buildForm(
$builder->add('ticket',new OpenTicketType());
$builder->add('comments','collection',array(
'type' => new VtigerTicketcommentsType()
使用这种方法,Ticket和Comment之间不需要有任何直接关系。
我已经找到了实现它的方法和问题。
关系如下:
crmentity.id
>Main,此表具有非关系
troubleticket.ticketid
>这与crmentity.id
有关
ticketcf.ticketid
>这与troubleticket.ticketid
有关
因此,插入时的顺序需要是crmentity
->troubleticket
->ticketcf
但是在Symfony2中,当你制作表单时,你必须创建最后一个表元素作为要生成的第一个表单,所以我会发布我的代码,以防有人和我有同样的问题。
http://pastebin.com/wLPyXvbj
:)