问题来了:
我有一个包含 3 个类的模型
一个人可以有多个工作,任何工作与人的关系都可以有“date_start”、“date_end”和“comment”属性。所以我用一个包含这些属性的可联合(person_job)构建了这个模型,并在称为 person 和 job 的 2 个 manyToOne 属性上建立了关系(用原则注释生成)
人物属性如下:
/**
* @var string
* @ORM\Column(name="name",type="string",length=255,nullable=false)
*/
private $name;
/**
* @var string
* @ORM\Column(name="firstname",type="string",length=255,nullable=true)
*/
private $firstname;
/**
* @var bool
* @ORM\Column(name="active", type="boolean")
*/
private $active;
作业属性如下所示:
/**
* @var string
* @ORM\Column(name="name",type="string",length=255,nullable=false)
*/
private $name;
person_job 看起来像这样:
/**
* @ORM\ManyToOne(targetEntity="...\Person")
* @ORM\JoinColumn(nullable=false)
*/
private $person;
/**
* @ORM\ManyToOne(targetEntity="...\Job")
* @ORM\JoinColumn(nullable=false)
*/
private $job;
/**
* @var string
* @ORM\Column(name="comment",type="string",length=255,nullable=true)
*/
private $comment;
/**
* @var \DateTime
* @ORM\Column(name="startdate",type="datetime")
*/
private $datestart;
/**
* @var \DateTime
* @ORM\Column(name="enddate",type="datetime")
*/
private $dateend;
现在我想为我的“人”构建一个表单,我可以在其中选择列表中的工作,并添加(如果需要)date_start、date_end 或与此工作相关的评论。对于“Person”,我的 FormBuilder 看起来像这样:
$builder
->add('name')
->add('firstname')
->add('jobs',Job::class,array('label'=>'Job'));
这失败了。我的 Person 类没有“工作”属性。那么,我怎样才能实现这样的目标呢?我是否必须添加一个 jobs 属性,上面有 oneToMany 关系,用“mappedBy”声明?
这些教义上的关系仍然让我感到困惑,我是 symfony 的新手,我在互联网上查看但还没有找到合适的解决方案/示例......
感谢阅读/帮助
最佳答案
您遇到了 Symfony 表单最棘手的问题之一。幸运的是,有一些很好的文档。让我总结一下重要步骤。
你是对的:实体 Person 需要知道它与 PersonJob 的关系,如果你想从 Person 的角度操纵这种关系。所以你需要添加一个属性:
// src/AppBundle/Entity/Person.php
/**
* @ORM\OneToMany(targetEntity="PersonJob", mappedBy="person")
*/
private $personJobs;
public function __construct()
{
$this->personJobs = new \Doctrine\Common\Collections\ArrayCollection();
}
然后您将在表单中输入
// src/AppBundle/Form/PersonType.php
$builder
->add('name')
->add('firstname')
->add('personJobs', CollectionType::class, array(
'entry_type' => PersonJobType::class,
'allow_add' => true,
)
;
注意 personJobs 字段的类型。由于一个人可以拥有多个 PersonJob,因此您需要一种可以处理集合的表单类型。这就是内置 CollectionType 的目的(查看 its documentation! )。您还需要表单类型 PersonJobType,以便 CollectionType 知道如何构建子表单:
class PersonJobType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('comment')
->add('datestart', DateTimeType::class)
->add('dateend', DateTimeType::class)
->add('job') // requires Job::__toString() to be defined!
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\PersonJob'
));
}
}
出于调试目的,将您的 Controller 更改为
public function testAction()
{
$person = new Person();
$form = $this->createForm(PersonType::class, $person);
$form->add('submit', SubmitType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
print '<pre>';
var_dump($form->getData());
die();
}
return $this->render('default/index.html.twig', [
'form' => $form->createView(),
]);
}
现在继续复制并粘贴 Adding and Removing Items 中的 Twig 和 Javascript 代码(您必须进行微小的更改,例如将 form.emails 替换为 form.personJobs)。
表单看起来像
只是带有“添加另一个 PersonJob” 链接的 Person 表单:
添加一个 PersonJob:
添加一个 PersonJob:
提交表单并查看 var_dump 的输出:
object(AppBundle\Entity\Person)#247 (5) {
["id":"AppBundle\Entity\Person":private]=>
NULL
["name":"AppBundle\Entity\Person":private]=>
string(12) "Charles Dude"
["firstName":"AppBundle\Entity\Person":private]=>
string(7) "Charles"
["active":"AppBundle\Entity\Person":private]=>
bool(true)
["personJobs":"AppBundle\Entity\Person":private]=>
object(Doctrine\Common\Collections\ArrayCollection)#248 (1) {
["elements":"Doctrine\Common\Collections\ArrayCollection":private]=>
array(2) {
[0]=>
object(AppBundle\Entity\PersonJob)#962 (6) {
["id":"AppBundle\Entity\PersonJob":private]=>
NULL
["comment":"AppBundle\Entity\PersonJob":private]=>
string(19) "Something important"
["datestart":"AppBundle\Entity\PersonJob":private]=>
object(DateTime)#1088 (3) { … }
["dateend": …] => …
["person":"AppBundle\Entity\PersonJob":private]=>
NULL
["job":"AppBundle\Entity\PersonJob":private]=>
object(AppBundle\Entity\Job)#1171 (2) {
["id":"AppBundle\Entity\Job":private]=>
int(2)
["name":"AppBundle\Entity\Job":private]=>
string(5) "Job 2"
}
}
[1]=> …
}
}
还有两件事要做:
将嵌套的 PersonJob 实体的 person 属性正确设置为新的(但尚未保留)Person。
通过调用 $em->persist(…) 告诉 Doctrine 关于新的 PersonJob 实体。
关于php - 具有 Symfony 3/Doctrine 属性形式的一对多对一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38048806/
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#
所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP
假设我有以下类(class):classPersondefinitialize(name,age)@name=name@age=ageenddefget_agereturn@ageendend我有一组Person对象。是否有一种简洁的、类似于Ruby的方法来获取最小(或最大)年龄的人?如何根据它对它们进行排序? 最佳答案 这样做会:people_array.min_by(&:get_age)people_array.max_by(&:get_age)people_array.sort_by(&:get_age)
我想为我的Task模型创建一个status属性,该属性将按以下顺序指示它在三部分进度中的位置:打开=>进行中=>完成。它的工作方式类似于亚马逊包裹的交付方式:已订购=>已发货=>已交付。我想知道设置此属性的最佳方法是什么。我可能是错的,但创建三个独立的bool属性似乎有点多余。实现此目标的最佳方法是什么? 最佳答案 Rails4有一个内置的enummacro.它使用单个整数列并映射到键列表。classOrderenumstatus:[:ordered,:shipped,:delivered]end状态映射如下:{ordered:0,