Dynamic Form Generation with Symfony2 - forms

The scenario is pretty simple, I want to enable adding product attributes in my webhop. So, I have product table which holds product information (price, description...), attribute table which defines all possible product attributes (color, weight, power...), product_attributes table which connects this two and holds actual attribute value (red, 25kg, 51w...).
I would like to enable product form to enable adding/editing this attributes (attribute set is defined in attribute table).
I tried using collections, but that allowed me to only edit existing product attributes, not to add new.
I also experimented with event subscribers, but everything I add does not fit in my Product entity, it is just not that flexible to accept anything, it asks for attributes.
Is there any good way to solve this problem?

You can accomplish what you want with Embedding Collection of Forms, and using some jQuery magic to make it pretty.
It's explained in detail in the guide. With collections you need to use :
'allow_add' => true, 'by_reference' => false,
to allow the users to add new attributes.

Related

How to model Database where a table entry can refer to another entry in the same table

I've a web app, being used by engineers for Asset(machines, scales) calibrations on a Site & certificate can be generated based on those readings. Up till now, the requirement was so that for a given SITE includes multiple ASSET and each asset has its own CALIBRATION.
So had my Modal like this.
With a recent change to include a new type of certificate. Where an ASSET can have multiple calibration (Two to be exact) one before Adjustment and One after if needed.
My question is, what is the best way to accommodate this change? Should I change the relation between ASSET one-to-one CALIBRATION to one-to-many with multiplicity (1..2) which basically requires to change lot of code check. or should adding another column in ASSET table which points to another entry within the same table. Or is there any other approach to opt ?
I'm using ASP.MVC, with Entity Framework.
Mapping
public Report_AssetMap()
{
HasKey(one => one.report_asset_id);
// Site_Report one-to-many-rel Report_Asset
HasRequired(one => one.Site_Report).WithMany(one => one.Report_Assets).HasForeignKey(one => one.site_report_id);
// Report_Asset one-to-one-rel Asset_Calcert
HasOptional(one => one.Asset_Calcert).WithRequired(ad => ad.Report_Asset).WillCascadeOnDelete(true);
}
public Asset_CalcertMap()
{
HasKey(one => one.report_asset_id);
// User one-to-many Asset_Calcert (with nullable Calcert_handled_by_id at many End)
HasOptional(o => o.Calcert_Handled_By).WithMany(r => r.Handled_Calcert).HasForeignKey(o => o.calcert_handled_by_id);
}
I would have a separate table for each of the pre and post adjustment certs; this is a solid use case for table-per-concrete-class inheritance (which is not yet included in EF Core but I'm guessing you're using EF6). Put common properties in a base class, derive a class for your pre and post adjustment certs (can be empty if no differentiation other than table names), then MapInheritedProperties and specify different table names for the derived classes in the model configuration.
https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines
If you then want to query against all Asset_CalCerts, you can specify a single DbSet<Asset_Caclert> DbSet in the DbContext to query while your Report_Asset entity can have a property referencing each derived Asset_CalCert type.
In this way you can keep your 1:? relationship while maintaining the ability to query all Asset_CalCerts as though they were in a single table.

In SugarCRM 7.5 Professional, how can you add custom relationship field?

In SugarCRM 7.5 when you open Contacts and view a record in the Opportunities subpanel you can link Opportunity record and set contact_role (Opportunity Role) that is a custom relationship field existing only in opportunities_contacts in the database.
Now I need the same functionality working with my two custom modules with many-to-many relationship between them and access_rights as the custom relationship field.
Two custom modules were created using Module Builder and deployed: c_Accounts, c_Users.
The many-to-many relationship between c_Accounts and c_Users was created in Studio.
in custom/metadata/c_accounts_c_usersMetaData I added
5 =>
array (
'name' => 'access_rights',
'type' => 'varchar',
'len' => 36,
),
and then Quick Repair & Rebuild. I accepted the SQL query and access_rights field was added to my relationship table in database.
Next, I added into both custom modules custom/Extension/modules/{module}/Ext/Vardefs/account_user_access_rights.php
and I was able to see the field in Studio subpanels and add the column to the subpanels view.
Now, the problem is the columns are shown properly in the subpanels for both custom modules but there is no data shown from the database. How to get the data from the link table into the subpanels?
After the above is accomplished. The next thing is to be able to edit/save the field in the subpanels.
The tools (such as Module Builder) do not support this out of the box. For example, the Contact Role field you mention is implemented as part of ContactOpportunityRelationship bean within Contacts module.
If you look at how the opportunity role is defined in Contacts metadata, you'll see you need to make sure to add the right "rname_link" to the field definition. This will make sure that SugarQuery (which is used to populate Subpanels in 7.5) adds the right Join to populate your subpanel.

Symfony2: Collection of dropdown select lists for a many-to-many relationship

The objective:
Having a many-to-many relation be displayed as a dynamic list of select inputs(single choice dropdown list)
User arrives on page with a single select field (multiple = false) populated with persisted entities and add/remove buttons. By clicking the add button, a new select field with the same options appears below the first, which adds a new entry in the M2M relation. By clicking remove the field disappears and the entry should be removed.
The model:
Two entities: User & Manager. A User has exactly one "special" Manager and unlimited normal Managers.
Managers manage unlimited users.To model this I have created two relationships for which the user is the "owner" (not sure how to translate this)
ManyToOne specialManager
ManyToMany normalManagers
I haven't created a many to many relationship with attribute "special" because the requirement is exactly one special manager and I wasn't sure if Symfony/Doctrine would cause problems down the line.
What I have:
I can display a multiple select field with the existing entities using Entity field type, as per the documentation. Functionally this is what I need, visually it is not.
I can also use the Collection field type to display a single text field, and add or remove more with JS, as per the documentation. Visually this is what I need, but The text fields (entity attribute) need to be replaced by choice field.
The question:
Before I continue digging, is there a simple way to achieve this list of select tags?
For anyone else who may eventually need a dynamic list of select fields:
I initially solved this issue by detaching the field(s) in event listeners, and handling the display/submission manually in the controller.
However I wasn't satisfied with this clunky solution and when I encountered the same need I used a second solution: creating an intermediary entity xxxChoice (in this case ManagerChoice) which is Mto1 inversed related to User and Mto1 related to Manager. Then by creating a ManagerChoiceType form with "Manager" entity field type I was able to easily display my collection of dropdown select lists.

How to handle autopopulated selects (from oneToMany relation) in Symfony form?

I have a ProductCategory class that has a parent and some children, properly annotated using Doctrine.
Then I have a ProductCategoryType (form class) that I use to render the html form.
Doctrine does its magic and creates a select box for parent which consists of previously added categories.
My problem: How to I prepend a default option (say '0' => 'No parent category') and how do I remove a particular category from list (ex: the currently edited category, so user can't select the very category to be its own parent)?
This can easily be achieved by using DataTransformers.
You can find more information in the documentation chapter How to use Data Transformers.

Foreign entity in form into different kind of input

I have two entities: product and category (Symfony 2.3).
I want to create a form in which an user can choose a product by first selecting the category. A user selects the category by clicking on image, then I want to set the image's value into a hidden input, but I don't see how can I change a foreign entity choice list to a hidden input (http://symfony.com/doc/current/reference/forms/types/entity.html).
How can I accomplish this? (how to change form input to hidden)
If I set cascade validation to true, will it for example check if a category really exist. (To prevent putting products with non-existing category from malicious users) ?
Part 1
To do this you need to use a data transformer to do two things:
transform an entity into an identifier that is either a string or integer so a form can render it as a hidden field.
transform the string or integer identifier into the entity when the form is submitted so that the parent entity can be saved with the correct relationship
The symfony docs I linked to above (here too) actually walk though an entire example of using a data transformer with a form.
As a shameless plug (because I believe it is helpful) I have written a little tutorial on using a data transformer for a hidden field with an entity id: http://lrotherfield.com/blog/symfony2-forms-entity-as-hidden-field/
Part 2
If you are using the data transformer then you don't need to worry about malicious users. The data transformer will fail because it will not be able to reverse transform the category from the fake id. In my tutorial the transformer will throw a Symfony\Component\Form\Exception\TransformationFailedException exception.
You can also write a validator (potentially using a call back) if you wanted that checks that the submitted category is real if you want an error to show in the form. Doctrine wont allow you to persist a fake category relationship as the foreign key constraint will fail.