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.
Related
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.
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.
I'm building a site that contains "panels" which are used as containers for various information. I have set it up so panels are editable, which is simple for panels that just contain text. For that I just grab the content from the database and wrap it in a textarea rather than a <p> tag. For panels that contain table views however this is proving to be a more difficult task.
First off I'm having trouble allowing the admin of the site pick what information is in a given table (for example if the admin wanted to add a panel view that showed each members first name, last name, and picture they could pick from those columns in my database). I've come up with a few ways to do this, but each have their own set of problems.
I tried using the INFORMATION_SCHEMA table to generate a table containing the possible tables and columns that the user can choose from. But when it comes to building the query with PDO I have problems. For instance with prepared statements you can't use a variable for the schema.
I also thought of using MySQL views but I can't seem to figure out how to do it that way either.
My second problem is allowing the admin to add rows to the tables directly. Right now all the add row template does is create a row with a text field in each column. This is good for purely text options (like first name) but for things like pictures obviously a text field won't work. Should I create a table that contains this metadata or perform the check in PHP? If it's the latter, how would I know what input type the column needs?
I think my main problem is I'm trying to solve too many things with only one design change (or not focusing on one problem at a time). It's resulting in me becoming very flustered and confused. Help is greatly appreciated and if you need anymore information like how my database tables are currently setup I'll provide an ERD.
Edit: I just wanted to make it clear that I don't want to allow the user to actually manipulate the tables in the database, but rather select what information from the existing tables is shown on a given panel.
Coding the ability for users to freely query a database has a lot of problems (including security) and is way more complicated than predefined information queries that simply return a defined set of information.
It also places the burden of defining which info might be useful onto the user. It places the burden of deciding whether a certain information should be accessible to a particular user onto the query logic and database access rules.
Effectively you are trying to copy PHPMyAdmin with a different design and only your defined database as a target.
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.
My question:
I have a mysql database that consists of something like a fact table (although not every field is a lookup) and a variety of other tables. When I want to display data from that "fact" table, is it necessary to run a query to each individual lookup or is there a way to make a temporary table that has already done the "looking up"?
Example:
Table structure -
unique_id(auto increment int),
model(int, lookup to table #2),
type(int, lookup from table #2 to table #3)
employee(int, lookup to table #4)
notes(text)
cost(float)
hours(float)
-
So for instance when I want to make a php page to enter this data it seems like a lot more "work" than it needs to be:
unique_id (not shown as a data entry field, increments automatically
on submit)
model (drop down box. population requires query to table #2 where status = X)
type (read-only text box shows type of model. Requires query to table #3 based on column from table #2)
employee (drop down box. population requires query to table #4 where employee_status = "Active")
notes (text box, user inputs related notes to submission)
cost (texts box, user enters costs related to submission)
hours (text box, user enters hours related to submission)
Just to get a simple form populated with valid data requires what seems to me like A LOT of queries/lookups.
Is this the best way? Is there a better way?
Aside: I have control over the data structure, so if the problem is the database design, then those suggestions would be helpful as well.
Dimension tables typically don't change very often, at least relative to the number of inserts to the fact table. Dimension tables are also individually much smaller than the fact table. This makes dimension tables good candidates for caching.
What some people do to good effect is to render the partial HTML output for the form, with all the data populated as dropdowns, radiobuttons, etc. Then store that partial HTML under a memcached key so you don't have to do any of the database queries or the HTML render for most PHP requests -- you just fetch the pre-populated HTML fragment out of memcached and echo it verbatim. I think of this like the "Ikea" of database-driven output.
Of course if you ever do change data in a dimension table, you'd want to invalidate the cached HTML, or even better re-generate it and store a new version of the HTML in memcached.
Regarding doing all the lookups, I'll point out that there's no requirement to use pseudokeys in a fact table. You can use the natural values, and make them reference the primary key of the dimension table, which also can be a natural key instead of a pseudokey. It might take a bit more space in some cases, but it eliminates the lookups. Of course it may make sense to continue using pseudokeys for dimensions that are long varchars.
I'm not quite sure what you mean by " a query to each individual lookup". Do you mean a way to save your entire table in your php script? Or do you mean a way to cache on the mysql server to eliminate process resources on the database node?
MySQL includes a built in Caching system that eliminates a lot of server cycles for similar queries. You can find more here-> MySQL Caching
As far as your database structure, you're going to have to provide a little bit more detail about your schema (What your database is meant to do) if you would like some suggestions. It's hard to know what kind of structure works and is effective without knowing what it's supposed to do. (Are there multiple notes per employee, what are costs? Are they per employee? etc)