Dynamic expansion of form input fields - php

I have been working on a web-based device management system for work, and I have ran into an issue with presenting the user the option of adding more fields as needed. For example, some devices will have say 4x drives, 6x ram modules, etc. My options so far are...
Hard-code the MySQL Database to have X amount of each type of field.
4 disk drive fields, 6 ram module fields, etc. However, most machines
will have less than this, and some may have considerably more.
Create a table for each type that will possibly have more than one
value. Such as a device_drives table, device_memory table, etc.
Would there be a more efficient (and dynamic) method of doing this? Both methods I have considered seem pretty silly. Here is a visual example of it, the red arrows representing icons that the user could click to add another of that type.

Why does it sound silly? Let's say you have one hundred million items in database. Do you alter that table every time a new field type is added? Does that sound smart?
I would suggest another solution. You could create a table for field types and another table for field values. This way you can separate the configuration data from the device data, which can be a good idea. No matter how many field types a device has, how many values every field has or in case of addition of a field type or value, you are still safe with this architecture.
As for visual creating of fields, you can simply add "+" at the right side, which is click-able and creates another similar field under the current one.

Related

How to structure MySQL db for storing multiple checkbox form data and later do statistics in php?

I am working on a form for storing information about the themes of the queries we receive in our company.
I am using php/MySQL to store radio button data such as:
Name of employee
Medium of query (e-mail/phone/in person)
With radio button data such as this, I can easily use PHP to query the database and e.g. count the numbers of queries answered by e-mail by each employee.
The trouble I am having is with data regarding the theme of the query. This is checkbox data with a lot of different checkboxes (50+). We would like to be able to add or remove checkboxes from time to time, though not very often.
I used to store this data just as comma-separated values in a single cell in the database and then export to excel to work with the data, but now I'd like to use another PHP form to generate statistics on the themes.
My research has lead me two to ways of doing this, that may be possible:
Creating a separate table in my database for my themes with one column for each possible theme, so that I'd have as many columns in my database as the number of checkboxes in my form.
Use the php functions serialize to store the checkbox data in one cell in my database and then later using unserialize to work with the data in php.
I am an absolute beginner, so with both options I'm unsure how I'd actually implement it:
With this option I am unsure whether my MySQL columns should just be "theme 1", "theme 2", etc., or whether they should have the names of my checkbox values, e.g. "money", "personal problems", "practical issues", etc. I have not been able to find a good resource on how to store the checkbox data in the right way, when the user may sometimes have clicked just 1 theme, and in other instances may have clicked 10 themes.
With this option I am unsure how I could populate a dropdown with unique values, and how I could later count instances of a unique value across the rows in my database.
Any help you can give me on this, including links to tutorials or questions similar to this on stackoverflow, would be much appreciated. I haven't been able to find anything about this that I could understand, other than I am thinking option 1 is probably the right way to go.
EDIT: After having received an idea about how to do this from David, I am updating my post with my attempt to understand how I would go about this.
What you're describing can be thought of as a many-to-many relationship. You have:
A form record, which can relate to many themes
A theme, which can relate to many form records
In a situation like this, the relationship itself is a database record. Consider this table structure:
FormRecords
----------
ID
SomeTitle
UserIDWhoFilledOutForm
etc.
Themes
----------
ID
ThemeName
etc.
FormRecordThemes
----------
FormRecordID
ThemeID
Each "primary entity" has an identifier and information about that entity. Then there's a "linking table" which has information about the relationship between those two entities.
Any time you present a form, you simply select from the Themes to populate the check boxes. You can add new ones as you see fit. You probably shouldn't remove any, though you can "soft delete" them by setting some flag on the record to indicate not to display them on the form.
If you ever want to edit the Themes in any significant way (a way which would somehow invalidate previous uses of that record, such as completely changing its name/title), then keep in mind that you'd be modifying the entire history of its use. I don't know if this is a risk in your domain, but in cases like that it might help to de-normalize a little bit by storing "Theme at that time" values in the relationship table. Like, the name of the Theme at the time that relationship was created. It's best to avoid this scenario entirely if possible, mostly by making key Theme values immutable in the domain.
Don't store delimited lists, don't store serialized data (unless the entire object really is a single data point)... Keep values separated into their own actual values in the database. Relational databases are really good at querying relational data.
You can put all values of checkboxes got from user into one CSV format string and store in one cell. Later on you can just split the string and get the values back.

Storing table structured form data into database - The proper way to do it?

This is going to be a long read, so please bear with me. I'm pretty good at PHP, but my knowledge in database designing is poor. I'm working on it as I've realized that having command over designing a database is the most important thing while working with applications and how things get so easier if you get the hang of it. The inception of this thread is also because of my weak knowledge about database interaction.
I basically have around 40 forms whose structure is similar to the image given below:
The number of columns and rows vary from one form to another, but they more or less follow a similar structure as shown above.
WHAT I'M PLANNING TO ACHIEVE
Use a single / same php page to process (i.e., insert data into
database) all the 40 forms. In other words, I intend to use the same <form
action="process.php"> for all the forms.
Avoid hard-coding; keep the code in process.php as much dynamic as
possible.
ROADBLOCKS
The number of parameters in each form vary, so I need to figure out a
way to find out the number of rows present in each form.
Finding it difficult to decide how to name the elements (radio
buttons, checkboxes, dropdowns, textareas, textboxes etc) being used
in the form.
I'm having trouble trying to figure out how to proceed with the
insertion. Inserting one row at a time seems to be appropriate, but
how would I achieve this? For example, if I use a loop, in the first
iteration data related to Ambiance should be inserted. In the
second loop data related to TV Room should be inserted and so on.
The problem is how to code accordingly?
WHAT I'VE IN MIND
The columns of the form (parameter, meets requirement, observation,
status, remarks) become the fields of the MySql table.
Then insert one row at a time in the table using a loop.
Use arrays for naming the elements used in the form. For example,
ambiance[requirement], ambiance[observation], ambiance[status],
ambiance[remarks] for elements in the first row and
room[requirement], room[observation], room[status], room[remarks] for
the second row and so on. Then insertion can be done in a single line
by using INSERT INTO tablename (implode(',', array_keys($ambiance)))
VALUES (implode(',', $ambiance))
WHAT THIS IS NOT ABOUT
Asking to supply / post code.
Give me teh codez is not my way of operating. I'm just seeking
instructions on how to go about with the task.
WHAT THIS IS ABOUT
Asking for suggestions.
Determining if I'm going in the right direction.
Asking if there are alternate ways.
I have done something similar but not exactly the same. I used these two tables:
Form
ID
Name (e.g. feedback, comments, survey)
FormFields**
ID
FormID
Caption (e.g. name, company, address)
SubCaption (e.g. enter your full name)
Required
DataType (e.g. integer, number, string, email)
MaxLength
** Look at the schema of a database table for more ideas.
In your case you need another pair of tables:
FormSubmission
ID
Date
FormSubmissionValues
ID
FormSubmissionID
FormFieldID (can be used to deduce FormID or you can add FormID in FormSubmission table)
Value (a field large enough to accommodate any value)
There were several catches. I'll note down a few:
The UI needs to vary depending on datatype (small 10 character input for integer/number, checkbox for boolean, textarea for text)
Not sure how to handle list boxes. Perhaps you need another table for this
You cannot use indexes properly since everything is stored in a generic text field
Client side validation is possible but difficult
The tables need to be very generic. Based on my experience this requires extra effort to ensure that x works with all y.

SELECT DISTINCT or separate normalized table?

We're making the plans now, so before I start progress I want to make sure I'm handing things in the best way.
We have a products table to which we're adding a new field called 'format', which is going to be the structure of the product (bag, box, etc). There is no set values for this, users can enter whatever they like into that field, however we want to show a drop down list of all formats that the user has already entered.
There's two ways I can think of to do that: either a basic SELECT DISTINCT on the products table to get all formats the user already filled in; or a separate table that stores the formats and is linked to by the product.
Instinctively I'd like to use SELECT DISTINCT, since it would make my life easier. However, assuming a table of a billion products, which would be the best way to go?
I think i would opt for the second option (additional table + foreign key if you want to add constraint), just because of the volume and because you can have management that will merge similar product form for example.
If you decide to keep everything in one table, then build an index on the column. This should speed the processing for creating the list in the user application.
I'm somewhat agnostic about which is the best approach. Often, when designing user interfaces, you want to try out different things. Having to make database changes impedes the creative process of building the application.
On the other hand, generally when users pick things from a drop down box in the application, these "things" are excellent examples of "entities" -- and that is what tables are intended to store.
In the end, I would say do what is most convenient while developing the application. As you get closer to finalizing it, consider whether it would be better to store these things in a separate table. One of the big questions is whether you want to know all formats that have every been used, even if no user currently has them defined.
Since you are letting users enter whatever they want I would go with the 2nd option.
Create a new table and insert in there all the new 'formats' and link to the product table.
Be sure when you create the code to add the format the user typed in, check if there is an equal value on the database so you won't need to distinct them as well.
Also, keep it consistent, either by having only the first letter upprcase of each word.

Optimal data storage - triple store / relational db / other?

I'm building a web-app with PHP on an Apache server.
The app contains a lot of optional data about persons. Depending on the category of the person (one person can be in may categories), they can choose to specify data or not: home-address (== 5 fields for street, city, country, ...), work-address (again 5 fields), age, telephone number, .... The app stores some additional data too, of course (created, last updated, username, password, userlevel, ...).
The current/outdated version of the app has 86 fields in the "users" table, and is (depending on the category of the person), extended with an additonal table with another 23 fields (1-1 relationship).
All this is stored in a Postgresql database.
I'm wondering if this is the best way to handle this type of data. Most records have (a lot of) empty fields, making the db larger and the queries slower. Is it worth looking into an other solution like a Triple Store, or am I worrying too much about it and should I just keep the current setup? It seems odd and feels awkward to just add fields to a table for every new purpose of the site. On the other hand, I have the impression that triple stores are not that common yet. Any pointers, or suggestions how to approach this?
I've read "Programming the semantic web" by Toby Segaran and others, but from that book I get the impression that the main advantage of triple stores and RDF is the exchange of information over the web (which is not the goal of my app)
Most records have (a lot of) empty fields
This implies that your data is far from normalized.
The current/outdated version of the app has 86 fields in the "users" table, and is (depending on the category of the person), extended with an additonal table with another 23 fields (1-1 relationship).
Indeed, yes, it's a very long way from being normalized.
If you've got a good reason to move away from where you are just now, then the firs step would be to structure your data much better. Even if you choose to move to a different type of DBMS e.g. noSQL or object db.
This does not just save space in your DBMS, it makes retrieving the data faster and reduces the amount of code you need to write (e.g. you can re-use the same code for maintaining a home address as maintaining a work address if you have a single table for 'address' with a field flagging the type of address).
There are lots of resources on the web (in addition to the wikipedia link above) describing how to apply the rules of normalization (it starts getting a little involved after 1,2 and 3 - but if you can master these then you're well equipped to take on most tasks).

Best way to display this in a form?

On my website, I have two tables which are linked using a pivot table. What I am trying to do is let a user update the relationships between the two tables (inserting and removing records from the pivot table). I have no problem doing this in PHP, but what I am concerned about is the way the form is displayed in the users web browser.
The way I am doing it now, is to have a table full of checkboxes, with each checkbox corresponding to a relationship between the column header and the row header (which represent the database tables). The user can check the checkbox to tell the PHP that a record should be present for that relationship (an unchecked box means there is no relationship). However this method can get quite ugly (columns stretching outside page bounds) if there are quite a few columns and quite a few rows, and is a bit tedious to use.
What would be a good way to display this form to the user?
Maybe use a data grid? These are quite powerful:
jQuery TableFilter (click "Go")
ExtJS Grid Filter (click a small down arrow ▼ that appears near the column name)
It may be a time consuming task to make it work through Ajax, though.
As this is more about the UI of the application than anything else, I don't think there is going to be a single right answer, as it will come down to a combination of what works (which is difficult without being able to see / play with things) and your personal preferences.
A few progressions I would run through:
Visual feedback
Make you table more interactive by providing visual feedback to the user. At the most basic level, try adding some colour to the cells - a colour for those that are checked. This will allow the user to quickly see which options are "in play". It may be the reverse of this works better (highlighting unchecked cells) - but this all depends what the form is doing / intending to indicate - i.e. if it's more important to make clear that the unchecked state is bad, you may want these to be red.
The next level up is to add some dynamic highlighting. If the table is huge, you may want to highlight the row and column header cells that correspond the the cell under the cursor. You could also consider highlight the whole row / column (cross-hair style) to allow the user to examine 'companion' cells.
Dynamic table
Slightly more involved would be to add some spice to you table. Instead of showing rows and columns of check-boxes, use graphical icons / images. They are a lot easier on the eye, and will probably allow you to have tighter control on the dimensions of the table. The entire UI could then be done via Javascript and on-click - which is pretty easy these days if you employ something like JQuery.
Split the interface
This is based on the assumption that all combinations of Table A & Table B aren't setup in the pivot table to begin with - only when a user tries to relate A.item with B.item
Instead of showing all possible combinations, show only those which are active (have an entry in the pivot table). Then provide the user with a second form (probably of two drop-downs) that allows them to relate a record from the first table to the second.
Filter the interface
Provide the user with the ability to filter the interface - to show only the relationships between a single record from one of the tables. This would have the effect of restricting your table to a single column, making it a bit easier to accommodate in the design.
However, I would still allow the user to get to the "big view" of all records, as, depending on what you are doing, such as view can be very useful to quickly cross reference lots of records.

Categories