我正在创建一个表单,以便能够向一组链接到特定类(class)的学生发送电子邮件。默认情况下,必须选择给定类(class)的所有学生,但消息的发件人必须能够取消选择学生以将他们排除在接收消息之外。发给全群没问题。从选择中删除学生时会出现问题。
我将 Sonata Admin 的 sonata_type_model 与自定义查询一起使用。在生成的表单上,如果我不更改选择选项并提交表单,一切正常。当我从列表中删除一个项目时,我在提交表单后收到错误消息:
错误:在/xxx/xxx/xxx/vendor/sonata-project/doctrine-orm-admin-bundle/Model/ModelManager.php line 607 中的非对象上调用成员函数 removeElement()
经过两天的寻找答案,希望这里有人可以帮助我朝着正确的方向前进。这是我使用的一些代码:
管理员:
$em = $this->modelManager->getEntityManager('Stnu\EduBundle\Entity\DealItem');
$query = $em->createQueryBuilder('d')
->select('d')
->from('StnuEduBundle:DealItem', 'd')
->innerJoin('d.deal', 'de')
->where('d.course = :course')
->andWhere('de.status = :status')
->setParameter('course',$course)
->setParameter('status','order');
$defaults = $query->getQuery()->getResult();
$formMapper
->with('Certificaten verzenden cursus \''. $title .'\'', array('description' => 'Begeleidende tekst e-mail'))
->add('dealItems', 'sonata_type_model', array(
'required' => true,
'expanded' => false,
'btn_add' => false,
'multiple' => true,
'label' => 'Verzenden aan',
'query' => $query,
'property' => 'deal.user',
'data' => $defaults,
'validation_groups' => false
))
->add('subject', 'text', array('required' => true, 'label' => 'Onderwerp', 'data' => $subject))
->add('body', 'textarea', array('label' => 'Bericht', 'required' => false, 'data' => $body, 'attr' => array('class' => 'tinymce', 'data-theme' => 'fullpage', 'style' => 'height: 350px')));
Controller :
/**
* Create action
*
* @return Response
*
* @throws AccessDeniedException If access is not granted
*/
public function createAction()
{
// the key used to lookup the template
$templateKey = 'edit';
if (false === $this->admin->isGranted('CREATE')) {
throw new AccessDeniedException();
}
$object = $this->admin->getNewInstance();
$this->admin->setSubject($object);
/** @var $form \Symfony\Component\Form\Form */
$form = $this->admin->getForm();
$form->setData($object);
if ($this->getRestMethod()== 'POST') {
$object->setDealItems($object->getDealItems());
$form->submit($this->get('request'));
错误出现在这一点之后。
实体:
<?php
namespace Stnu\EduBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* DocsEmail
*
* @ORM\Entity
*/
class CertificateEmail {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="DealItem")
* @ORM\JoinTable(name="certificateemails_dealitems",
* joinColumns={@ORM\JoinColumn(name="certificateEmail_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="dealItem_id", referencedColumnName="id")}
* )
*/
private $dealItems;
private $subject;
private $body;
private $extraEmailTo;
public function __construct() {
$this->dealItems = new ArrayCollection();
}
/**
* Add dealItem
*
*/
public function addDealItem(\Stnu\EduBundle\Entity\DealItem $dealItem) {
$this->dealItems->add($dealItem);
//$this->dealItems[] = $dealItem;
return $this;
}
/**
* Remove dealItem
*/
public function removeDealItem(\Stnu\EduBundle\Entity\DealItem $dealItem) {
foreach ($this->dealItems as $item) {
if ($dealItem === $item) {
// manager of Stnu\EduBundle\Entity\DealItem
$entityManager->remove($dealItem);
}
}
}
/**
* Get dealItems
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getDealItems() {
return $this->dealItems;
}
public function setDealItems($dealItems) {
$this->dealItems = new ArrayCollection();
if (count($dealItems) > 0) {
foreach ($dealItems as $dealItem) {
$this->addDealItem($dealItem);
}
}
return $this;
}
/**
* Set subject
*
* @param string $subject
*/
public function setSubject($subject) {
$this->subject = $subject;
return $this;
}
/**
* Get subject
*
* @return string
*/
public function getSubject() {
return $this->subject;
}
/**
* Set body
*
* @param string $body
*/
public function setBody($body) {
$this->body = $body;
return $this;
}
/**
* Get body
*
* @return string
*/
public function getBody() {
return $this->body;
}
/**
* Set extraEmailTo
*
* @param string $extraEmailTo
*/
public function setExtraEmailTo($extraEmailTo) {
$this->extraEmailTo = $extraEmailTo;
return $this;
}
/**
* Get extraEmailTo
*
* @return string
*/
public function getExtraEmailTo() {
return $this->extraEmailTo;
}
}
希望有人能帮帮我!
最佳答案
我相信这离您的问题的答案越来越近了。问题是,你完全问错了问题。重要的东西在下面,在“编辑 - 自定义多选字段”下。
您的removeDealItem 方法完全错误。试试这个:
public function removeDealItem(\Stnu\EduBundle\Entity\DealItem $dealItem)
{
$this->dealItems->removeElement( $dealItem );
return $this;
}
您没有$entityManager 可以在这里调用……您也不需要。 Doctrine 将检查您要删除的实体是否存在,如果存在则将其删除。您不需要遍历集合中的现有元素,当然也不需要在数据库级别执行任何操作。
public function addDealItem(\Stnu\EduBundle\Entity\DealItem $dealItem)
{
// Getting fancy - check if the item exists before adding it
if( !$this->dealItems->contains($dealItem) )
{
$this->dealItems->add($dealItem);
}
return $this;
}
添加一个项目同样简单……我们甚至可以花点心思,使用 Doctrine ArrayCollection::contains() 方法在添加元素之前检查它是否存在。您的 addDealItem() 方法没有任何问题 - 我只是想向您展示 contains() 作为让 ArrayCollection 类更直观的说明为您完成工作。
编辑 - 自定义多选字段
好的 - 在阅读了您关于不一定需要保留数据的评论后,我想我应该提供这个简化的示例来说明如何创建自定义多选框。请理解,这是一个“基础知识”示例 - 但它应该引导您朝着正确的方向前进。显然,在不知道您的 DealItem 实体结构的情况下,我只是猜测您需要访问哪些特定字段才能获取发送电子邮件所需的数据。
所以 - 在您的 Controller 中 - 首先我们获取数据:
$query = $em->createQueryBuilder('d')
->select('d')
->from('StnuEduBundle:DealItem', 'd')
->innerJoin('d.deal', 'de')
->where('d.course = :course')
->andWhere('de.status = :status')
->setParameter('course',$course)
->setParameter('status','order');
$defaults = $query->getQuery()->getResult();
$choices = array();
foreach( $defaults as $dealItem )
{
$choices[ $dealItem->getEmailAddress() ] = $dealItem->getStudentName();
}
现在我们需要一个对象来接收数据。我从您的评论中收集到的是您不想保留数据,并且您只为您的 CertificateEmail 对象创建了一个实体,以便您可以构建一个表单。馊主意。 您不需要实体 - 所以一开始就不要构建实体。为了证明这一点,我将使用 stdClass 对象来实现:
$certificateEmail = new \stdClass();
$certificateEmail->dealItems = array();
$certificateEmail->subject = '';
$certificateEmail->body = '';
然后我们构建表单:
$form = $this->createFormBuilder( $certificateEmail )
->add( 'dealItems', 'choice', array(
'choices' => $choices,
'multiple' => true,
'required' => true,
'label' => 'Verzenden aan' ) )
->add( 'subject', 'text', array( 'required' => true, 'label' => 'Onderwerp' ) )
->add( 'body', 'textarea', array( 'required' => false, 'label' => 'Bericht' ) )
->getForm();
最后,把它扔到一个模板上:
return $this->render( 'template.html.twig', array( 'form' => $form->createView() ) );
而且,希望你可以从那里开始:)
关于php - 在非对象上调用成员函数 removeElement(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32779205/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs