Database structure for Tests - php

well, im really new to mysql, and i have no idea to do what i am intending to, or atleast not the efficient way.
i have to make a database that will hold people's information
within it every person has 3 courses to pass(courses as in educational courses) lets say its stage 1, 2 and 3, they cannot start course 2 without completing course 1
every course has 10 tests, they have the same name (eg. there is a test called example1 in course1 and also a test called example1 in course2, but its more difficult)
there aren't grades, just passed or failed
and lastly they are permitted into taking each test 3 times, i want to store the date(every try) and also who was the applier of the exam(every try), the names of the "teachers" are on a table

It is not a matter of mysql or php.
You should learn about Database Modelling.
And then use any of these tools (I like DB Designer for modelling)
Then you should learn how to integrate PHP and MySQL

Try Sakila database created by mySql, this is an example database used for training. You'll learn a few tricks from there, quite useful before creating your own database or maybe even before reading some books or the theme.

In additon to patricio's answer (which I consider valuable and good pointers). Take what you have written above and extend it. Find the key works in your description (i expect this will include people, course, test ...). For each key word identify all details you need to hold.
E.g. "I have to make a database that will hold peoples information" And for people I need to know ... maybe first name, last name, data of birth, employee number, etc. What ever details of a person is relevant to you. List them in a spreedsheet or document. Repeat this for each key word.
Then consider items you need to know to run the system, your last bullet point heads in this direction. Identify any new key words from that and then details you need to know about those key words.
Take your list of details and normalise it. As a general rule of thumb aim for 3rd normal form. In most cases it appears to be a workable compromise between higher levels of normalisation and not doing it. Maybe one of those 80/20 rules where by with 20% of the effort it takes to get there (as opposed to normalising to 6th normal form) you get 80% of the benefit of normalising.
Put together a proposal and feel free to come back for us to critique it if you want.

Related

What is the best way to wait that an administrator validate something before comitting it?

I'm building a web application where several groups have their own page but if they want to modify it, an administrator has to validate it before.
For example, can change to change its logo, post new photo, change their phone number, their name, their location etc... Basically they can edit a value in the database but only if the administrator accepts it. The administrator has to validate every modification because... our customer asked us to.
That's why we have to create a system that could be called "pending queries" management.
At the beginning I thought that keeping the query in the database and executing when an administrator validate it was a good idea, but if we choose this option we can't use PDO to build prepared statements since we have to concatenate string to build our own statement, wich obvious security issues.
Then we thought that we should keep PHP code that calls the right methods (that use PDO) in our database and that we will execute with eval() when the administrator validates it. But again, it seems that using eval() is a very bad idea. As says this Rasmus Lerford's quote : "If eval() is the answer, you're almost certainly asking the
wrong question".
I thought about using eval because I want to call methods that uses PDO to deal with the database.
So, what is the best way to solve this problem ? It seems that there is no safe way to implements it.
Both your ideas are, to be frank, simply weird.
Add a field in a table to tell an approved content from unapproved one.
Here's one possible approach, with an attempt to keep the things organised to an extent, as the system begins to scale:
Create a table called PendingRequests. This will have to have most of the following fields and maybe quite a few more:
(id, request_type, request_contents, reqeust_made_by, request_made_timestamp,
request_approved_by, request_approved_timestamp, ....)
Request_contents is a broad term and it may not just be confined to one column alone. How you gather the data for this column will depend on the front-end environment you provide to the users (WYSIWYG, etc).
Request_approved_by will be NULL when the data is first inserted in the table (i.e. user has made an initial request). This way, you'll know which requests to present in the administration panel. Once an admin approves it, this column will be updated to reflect the id of the admin that approved it and the approved changes could eventually go live.
So far, we've only talked about managing the requests. Once that process is established, then the next question would be to determine how to finally map the approved requests to users. As such, it'd actually require a bit of study of the currently proposed system and its workflow. Though, in short, there may be two school of thoughts:
Method 1:
Create a new table each for everything (logo, phone number, name, etc) that is customisable.
Or
Method 2:
Simply add them as columns in one of your tables (which would essentially be in a 1:1 relationship with the user table, as far as attributes such as logo, name, etc. are concerned).
This brings us to Request_type. This is the field that will hold values / flags for the system to determine which field or table (depending on Method 1 or Method 2) the changes will be incident upon - after an admin has approved the changes.
No matter what requirement or approach it is to go about database management, PHP and PDO are both flexible enough to help write customisable and secure queries.
As an aside, it might be a good idea to maintain a table for history of all the changes / updates made. By now, it should probably be apparent that the number of history tables will once again depend on Method 1 or Method 2.
Hope that helps.

Why use IDs for looking up data as opposed to using the title -- please help me argue my point

Please help me argue my point.
I am working on a website project with a team of developers, we are developing the system in 3 parts. The one part is the API, 2 back-end and front-end. Both the front end and back-end gets and stores data by sending it to the API.
I am specifically responsible for the front end. I am using Codeigniter as my framework.
A little background: The app is a sports betting site.
This is the problem: The developers of the API use the name of for example a tournament or fixture or sport to do the lookup, I pass the name of a tournament for example:
www.example.com/sport/add_bet/{tournament_name}
The problem I have with this is that the tournament name as entered into the system by humans might have characters such as spaces, forward slashes, etc in the name.
As you can imagine using a forward slash in the url will completely break the system, since we use them to call different controllers, actions and to pass variables.
I am trying to get them to change to using a simple primary key id field, to perform the lookup of the data. For some reason these developers don't want to do this.
The project manager that manages this project (not a programmer and no experience of programming) had a chat to them about this issue, but still they don't want to change, and they told her that it is a matter of personal preference on which way to go.
As far as I know ID's have always been the way to do it.
Could you guys/girls please help me argue my point by giving some reasons as to why I am correct or incorrect in your view. I would like to provide your answers as motivation to get them to change over to doing it the right way.
Your help/answers/suggestions would be much appreciated.
The most important thing is the id will be unique as it is should be the primary key. so searching by ids will return unique results.
But the multiple record may have save title if you didn't validate them at the time of saving.
And also if you want some joins or something like that the id would help it.
And the should never trust the user and expect them to work as you wanted.
There is two sides:
1) You allow select single Title from dropdown and send to server only ID. Look-up by ID is way faster (assuming you are using ID as primary key). But if you have lots of Titles than you have to list all of them and user will be forced to scroll till find that Title.
2) You have simple input field to allow search only by part of Title. That way you don't have to list all Titles. As programmer, you have to escape all user input, that goes to server (via GET or POST), so that user can input even DELETE FROM user WHERE 1 to your input field and your system will sill works fine. Also, by inputting only part of Title allow to show multiple results, while using IDs is impossible.
I prefer second approach.
To make the look up fast, you need to place an index on the column by which you are looking up records. Primary key column always has an index. In order to use some other column you need to add an unique index, to avoid duplicates and make the search faster, which in turn makes the table larger. If you expect the table to grow (which is not too unlikely if you follow many sports and many leagues/tournaments over a number of years), it might become a problem at some point, depending on the resources in your production environment. It's not the strongest argument you can present, but it is not a bad argument either

Logging user activities in applications

The problem I'm here to talk about and (ask about of course) is not new. I searched web and stack overflow and I got ideas to many part of this problem (pros and cons) but there is still some part missing in my mind. So I thought it would be a good idea to share in one place (of course it will be more complete with others' ideas) and ask for it.
The problem is clear: "We Want to log every single action of user" - probably when we solve the big problem, smaller ones (like logging only one action would be piece of cake).
First from what I read over the web and stack overflow:
Use DB instead of File: That's a good advice although it always depends on situation. But because of many benefits of DB, in long term and in general, it's the better solution.
DB Layer or Application Layer: Actually it depends. For example If you want really monitor everything(I mean really every single rows that changes in Database, it seems we will have one choice "Using Database Triggers". Although there are many discussions around MySQL that says, triggers slowdown DB and they advised not to use it. So it depends on the level of details you need, you can put your logging system in DB Layer or Application Layer(for exam some common function call $logClass->logThis()).
Use Observers: Clean codes are always better. If you are familiar with observers, you can use them to do things for you when an action is happened so you don't have to add $logClass->logThis() every time a CRUD happens in your application.
What To Log: Simple and short answer is: Based on your needs, but there are some common fields you will need:
user_id (if a unique user ID is available)
timestamp (unix maybe)
ip (not everyone know how to fake it in first place so use it, even faking it give you some insight about user behavior)
action_id (should be predefined actions for better unifying in queries and reports)
object_id (the unique row ID of a record that changes had made on)
action (which my question is about this part)
and etc...
I would appreciate if anyone correct me if I made mistake in any part or add other useful information to this post, so it would become one of good references for other users.
And now my question: How to Store actions?. For better understanding, consider following scenario.
I have a table named "product" and a table named "companies". From the business logic we want to assign products to companies, which we ended up in a table "company_product". Now when a user insert new product and simultaneously assign it's companies, 2 table will be affected (the same goes for delete and update): "product" and "company_product" and we want to know:
what's inserted?
what's deleted?
what's updated to what?
For performance issue and because I don't have enough knowledge about triggers, I want to use logging in Application Layer, so I ended up with this idea that I can, save action fields of database in array or json structure. But as I developed my solution I encountered a problem: How to make this log understandable for non technical users? Because for example I want to save something like this in action field of database when delete(insert) product with id 20:
action : [{id: 20, product_id:2, company_id: 1},{id: 21, product_id:2, company_id: 2}]
And this is not something easy for every one to read and understand. Actually I can use this json more readable and make it something like this:
action : {'Product A Deleted From Company X', 'Product A Deleted From Company Y'}
and save the previous action in technical_action field for further diagnose, But it needs additional works and more query to run for something that is not always needed to be considered(log)
I would appreciate any additional information on this article (I'm definitely sure that there exist other criteria that can be discussed), and answer to my question.
You are actually going to gather details for analytics kind of stuffs.
It will be good if you go for flat tables rather than going to relational tables.
Because if you want to do more analysis your relational table will not be a good choice as it lacks in performance.

Is it a good practice to use different table for different (but similar) business program?

There's a very similar question: Modeling products with vastly different sets of needed-to-know information and linking them to lineitems? But I can't find an answer that help me;
Someone at the above Q&A points to designing database to hold different metadata information , which has a fantastic accepted answer, but since search function is explicitly needed in my program, I don't want performance to be compromised.
I'm a "technician" that uses PHP + Oracle to keep track of the selling progress of our company and generate reports. Our workflow generally looks like this:
Marketing guys provides prepared data-set to my system;
Frontline staffs (sales) mark progress on my system;
Anyone can search results in the system;
I generate reports back to marketing guys.
The problem:
Many columns of data-sets are the same (or can be considered the same), like these:
account|customer_name|gender|location|program_segment|...
But the marketing dept. like coming up new ideas (and abandoning existing ones), so each "sales program (campaign)" may has its own data, e.g.
For program 1, they may contain:
...|prev_coupon_code|last_usage_amount|...
For program 2, however, they may contain:
...|is_in_plan_1|is_in_plan_2|...
You got the idea.
Unsuccessful attempts:
In order to hold all data, I used to use a "long enough" table that has all possible properties (columns), and leave blank/unnecessary properties NULL.
But now I feel that it will never be "long enough", as there're too many "properties" and even more "sales focusing point": I drafted a 41 column table for a new version of the system and suddenly they proposed a new program that has information that can't fit.
Someone suggested me to create "dummy columns" in the table and "remember" different meaning of them in frontend. This can work for several datatypes, like NUMBER(1) for Y/N, DATE, etc., but when talking about VARCHAR2, I'm not sure how many of that is enough...plus this makes the table look "dirty".
Question:
Frustrated, I'm now seriously considering using different tables for different programs, and use UNION clause to generate big report in case they're asked "how are we selling this month/season/year?"
Technically, is this a good practice? Should I implement it?
Edit #1:
To clarify, one "sales program" will generally be running for a few months before it got abandoned, and there'll be at least one data-set per month for each running program.
And there can be more than one program running at the same time.
Edit #2:
Those "program-specified" columns are of various number: one program may need 10, while another may only need 1.
This is one of those situations where there is no right answer, just a choice of kludges.
I would plump for using an XMLType to hold the transient data structures. XML gives us the ability to have defined schemas for each plan, but using an XMLType obviates the need to change the database itself. We can index XPath queries so the performance can still be good. Find out more.
The one problem is that writing queries against XML is a bit of a pfaff, but I think awkward queries will be an issue for whichever apporach you take.
You may or may not be aware that it is possible to index the contents of a character LOB in Oracle. You might look up Oracle Intermedia / multimedia (depends on your version) and talk to your DBAs to see if it is available to you.
This would make it possible to create a common structure for common data items - eg campaign, start_date, end_date, &c but then to dump your spreadsheet/xml data/csv file into a CLOB field.
The plain-text indexing is not as hard as it first sounds and it is very cute indeed.
If you go down the different table path you will forever be changing code to meet the changing columns etc.
One option would be to have 2 additional columns 'campaign_name', 'campaign_value' and put the column name they send you in the NAME column and the value in the value column.
So,
account|customer_name|.....|campaign_name|campaign_value
'ACC001'|'Frank Burns'|........|'prev_coupon_code'|[value of prev_coupon_code
and then in your 2nd example:
account|customer_name|.....|campaign_name|campaign_value
'ACC001'|'Frank Burns'|........|'is_in_plan_1'|[value of is_in_plan_1
Update - yes, this would involve changing the grain of the table so you would add a set of data for each of the campaigns.
The import would be a little different in that you'd UNION the records for each of the column names that appear on there, and the reporting would need to take into account the grain change.
It sounds like a complete waste of space, but if these are Excel sheets then performance shouldn't matter. If it did you would need to split the tables into
- campaigns, accounts, accounts_campaigns
On my current job, I successfully use following system for 2 years.
You have one main table, let's say 'report', that consist of common columns for all kind of reports.
id - primary, auto_increment.
name - name of the report.
Then, for each specific report, you have another table, called something like "report_marketing". There you have report_id column, that is foreign key to first main table. And here you add all specific columns for this specific report.
To get results, you simply use LEFT JOIN.
If some reports share some columns from 2 or more tables, you can always join more than one column.
Here is example of query you might have:
SELECT report.name, report_marketing.ammount FROM report WHERE report.type = 'M'
LEFT JOIN report_marketing ON report_marketing.report_id = report.id;

Creating Interactive Product Selector with PHP

I am wanting to do something similar to this:
http://www.dimarzio.com/pickup-picker
My question involves the concept rather than any specific code on how to execute this.
For example, we are selling violins and we want the user to input info about their playing style, and give them the three best violins based on their entry. This is the data I've been given:
So if the user inputs Expert, Hard, Rock, and Dark I will get data sets of violins consisting of: Cannon, Soil, Ysaye, K.Joseph, Heifetz // Cannon, Kreisler, Soil, Heifetz // Kreisler, Diable, Vieuxtemps // Cannon, Diable, Plowden
Out of those I need to output to the user the three best choices for them. Cannon is listed in 3 out of the 4, so that has to be #1. Now there are three more violins that match two of the four criteria. The Soil, Kriesler and Diable. In order to drill that down to two choices, I would think the questions would have to be ranked according to importance. For instance Tone is most important, followed by bowing style, musical genre, and skill level. Based on that ranking, the program should choose the Diable and Kreisler.
I am not entirely sure how to approach this. Since this data will not change frequently, should this even get the database involved? Should the info just be stored in a multi-dimensional array? Once the data is in an array, whether from the DB or not, how should I go about programming the logic to examine the arrays in order of importance and grab the violins that are most relevant?
Any help is much appreciated! I figured this was going to be easy, until I actually started thinking about it!
To me this sounds like a sorting problem. I don't know anything about violins so I'm unable to absorb much from your example, but anyway...
You're probably familiar with how a database sorts across multiple columns. If I said order by firstname, lastname, phone it would compare the firstnames, and only if theres a tie, would it then compare the last names, and again if there's a tie, then it would compare the phone numbers.
Once sorted, you pick the top N entries and display.
You can do custom sorting like this in php code too. For example, you would want to order by num occurances in a list, tone, bowing style, etc...
Thats the gist of it. I would store it in a database merely because its data and for the most part, its a great place to keep it. Plenty of import export and other data management, viewing, editing and other functionality freebies come with using a database.
If you need some sample code that mimics the database order by clause, I can dig some up I know I have somewhere.
We have a start up company that solves the issue you are outlining. Basically we have created a semantically enabled product selector which guides users through a selection process to find a product or a solution.
Although we have designed our product for a different market sector (not vioins), I think it would help to solve the issue you describe.
The data is hosted on Amazon AWS and we have built an API so the product selector can be incorporated into iPhone apps, Android apps, websites etc.
If you want, our website www.productworld.com where you will get my contact details.

Categories