Dynamic project data managment with forms and mysql - php

I am currently responsible for creating a web based project management application for the department I work in. Each project has a bunch of different data points that describe it and my first plan was to just set up a table in the mysql database and an html form to manage the data in that table.
My managers just let me know they will need to be able to add/delete data points for the projects in case their work flow and project tracking changes. (This would be something that happens MAYBE a few times a year if at all)
So I am attempting to figure out the best way to go about storing this data in MySQL. The first approach that came to mind was give them an interface that allows them to add columns to the 'projects' table. and have a 'master' table that tracks all the column names and data types. But that feels like a REALLY Bad idea and a bit of a nightmare to maintain.
Another possible option would be to have the interface add a new table that stores all the information for that data point AND the id of the project that is using the data.
I understand that both of these could be really screwy ways of doing things. If there is a better way I would love to hear about it. If I need to clarify something let me know.
Thank you for your time

CREATE TABLE projects (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
)
CREATE TABLE datapoints (
id INT PRIMARY KEY AUTO_INCREMENT,
projectid INT NOT NULL,
name VARCHAR(50) NOT NULL,
value VARCHAR(250) NOT NULL,
INDEX(projectid),
INDEX(name)
)
If you want more fancy, do one or more of
Put datapoint names in a table, reference them isnstead of naming them in table datapoints
Have datapoints have a field for each of numeric, pit, text, longtext OR use different tables

Related

way to manage audit trail of changing record in mysql

I am building a application. It is basically a E-commerce Order fulfillment application. IN this audit trials i.e. who changed what and how many times it was changed and others make a important aspect. How should i maintain this in database / table level ? Say if a record is altered by 3 people, how will i maintain all the changes and track of who changed what ?
First, you need create for every table which you want track with structure like this:
create table user_track_logs {
id bigint(20) primary key auto_increment,
key_id int (11),
user_id (int),
created timestamp default now(),
field varchar(128)// set bigger if you have long named columns (like this_columns_is_very_important_for_me_and_my_employers...)
field_value_was text null,
field_value_new text null,
}
Second you need set current user ID in var in MySQL's connection, or you can use MySQL's user. You can create for every user separate MySQL's login.
Third create triggers insert/update/delete which will be store in user_track_logs.
Or you can emulate this process in PHP, but in PHP it will be more difficult.

MySQL Database I18N, a JSON approach?

UPDATE: I've come across this question I did after some years: now I know this is a very bad approach. Please don't use this. You can always use additional tables for i18n (for example products and products_lang), with separate entries for every locale: better for indexes, better for search, etc.
I'm trying to implement i18n in a MySQL/PHP site.
I've read answers stating that "i18n is not part of database normally", which I think is a somewhat narrow-minded approach.
What about product namesd, or, like in my instance, a menu structure and contents stored in the db?
I would like to know what do you think of my approach, taking into account that the languages should be extensible, so I'm trying to avoid the "one column for each language solution".
One solution would be to use a reference (id) for the string to translate and for every translatable column have a table with primary key, string id, language id and translation.
Another solution I thought was to use JSON. So a menu entry in my db would look like:
idmenu label
------ -------------------------------------------
5 {"en":"Homepage", "it":"pagina principale"}
What do you think of this approach?
"One solution would be to use a reference (id) for the string to translate and for every translatable column have a table with primary key, string id, language id and translation."
I implemented it once, what i did was I took the existing database schema, looked for all tables with translatable text columns, and for each such table I created a separate table containing only those text columns, and an additional language id and id to tie it to the "data" row in the original table. So if I had:
create table product (
id int not null primary key
, sku varchar(12) not null
, price decimal(8,2) not null
, name varchar(64) not null
, description text
)
I would create:
create table product_text (
product_id int not null
, language_id int not null
, name varchar(64) not null
, description text
, primary key (product_id, language_id)
, foreign key (product_id) references product(id)
, foreign key (language_id) references language(id)
)
And I would query like so:
SELECT product.id
, COALESCE(product_text.name, product.name) name
, COALESCE(product_text.description, product.description) description
FROM product
LEFT JOIN product_text
ON product.id = product_text.product_id
AND 10 = product_text.language_id
(10 would happen to be the language id which you're interested in right now.)
As you can see the original table retains the text columns - these serve as default in case no translation is available for the current language.
So no need to create a separate table for each text column, just one table for all text columns (per original table)
Like others pointed out, the JSON idea has the problem that it will be pretty impossible to query it, which in turn means being unable to extract only the translation you need at a particular time.
This is not an extension. You loose all advantages of using a relational database. By way like yours you may use serialize() for much better performance of decoding and store data even in files. There is no especial meen to use SQL with such structures.
I think no problem to use columns for all languages. That's even easier in programming of CMS. A relational database is not only for storing data. It is for rational working with data (e.g. using powerful built-in mechanisms) and controlling the structure and integrity of data.
first thought: this would obviously brake exact searching in sql WHERE label='Homepage'
second: user while search would be able to see not needed results (when e.g. his query was find in other languge string)
I would recommend keeping a single primary language in the database and using an extra sub-system to maintain the translations. This is the standard approach for web applications like Drupal. Most likely in the domain of your software/application there will be a single translation for each primary language string, so you don't hav to worry about context or ambiguity. (In fact for best user experience you should strive to have unique labels for unique functionality anyway).
If you want to roll your own table, you could have something like:
create table translations (
id int not null primary key
, source varchar(255) not null // the text in the primary language
, lang varchar(5) not null // the language of the translation
, translation varchar(255) not null // the text of the translation
)
You probably want more than 2 characters for language since you'll likely want en_US, en_UK etc.

Figuring out the most effective way for a custom database server (PHP)

I just came across the idea of writing a special database which will fit for exactly one purpose. I have looked into several other database-systems and came to the conclusion that I need a custom type. However my question is not about if it is a good idea, but how to implement this best.
The application itself is written in php and needs to write to a custom database system.
Because there can be simultaneous read/write operations I can forget the idea of implementing the database directly into my application. (correct me please if I'm wrong).
That means I have to create 2 scripts:
The database-server-script
The application.
This means that the application has to communicate with the server. My idea was using php in cli mode for the database-server. The question is, if this is effective, or if I should look into a programming language like c++ to develop the server application? The second question is then the communication. When using php in cli mode I thought about giving a serialized-array-query as a param. When using c++ should I still do it serialized? or maybe in json, or whatever?
I have to note that a database to search through can consist of several thousands of entries. So i dont know exactly if php is realy the right choice.
Secondly i have to note that queries arent strings which have to be parsed, but an array giving a key,value filter or dataset. The only maybe complexer thing the database server has to be able to is to compare strings like the MySQL version of LIKE '%VALUE%', which could be slow at several thousand entries.
Thanks for the Help.
writing a special database which will fit for exactly one purpose
I presume you mean a custom database management system,
I'm having a lot of trouble undertanding why this would ever be necessary.
Datasbes and Tables like usual databases have. But i dont have columns. Each entry can have its own columns, except for the id
That's not a very good reason for putting yourself (and your users) through a great deal of pain and effort.
i could use mysql id | serialized data... but then much fun searching over a specific parameter in a entry
So what's wrong with a fully polymorphic model implemented on top of a relational database:
CREATE TABLE relation (
id INTEGER NOT NULL auto_increment,
....
PRIMARY KEY (id)
);
CREATE TABLE col_string (
relation_id NOT NULL /* references relation.id */
name VARCHAR(20),
val_string VARCHAR(40),
PRIMARY KEY (relation_id, name)
);
CREATE TABLE col_integer (
relation_id NOT NULL /* references relation.id */
name VARCHAR(20),
val_integer INTEGER,
PRIMARY KEY (relation_id, name)
);
CREATE TABLE col_float (
relation_id NOT NULL /* references relation.id */
name VARCHAR(20),
val_float INTEGER,
PRIMARY KEY (relation_id, name)
);
... and tables for BLOBs, DATEs, etc
Or if scalability is not a big problem....
CREATE TABLE all_cols (
relation_id NOT NULL /* references relation.id */
name VARCHAR(20),
ctype ENUM('string','integer','float',...),
val_string VARCHAR(40),
val_integer INTEGER,
val_float INTEGER,
...
PRIMARY KEY (relation_id, name)
);
Yes, inserts and selecting 'rows' is more complicated than for a normal relational table - but a lot simpler than writing your own DBMS from scratch. And you can wrap most of the functionality in stored procedures. The method described would also map easily to a NoSQL db.

I need a unknown amount of coordinates field (or few fields) How to go about doing this?

Using MySQL I need to have a list (possibly long list) of x,y coordinates. How should I go about this?
Apologies for the amazing amount of vague in this question! I didn't want to explain my entire project but I suppose some more explanation is in order for this to make any sense as a question.
Ok I'm doing a a map/direction web application for a client (no, I've looked into Google Maps API, but I need to map their buildings/campus so I don't think that applies well). So my current plan is to create some PHP scripts that will run through dijkstra's algorithm (I'm purposely dumbing this down quite a bit because, again, I don't want to explain the whole project) but since that algorithm is based on the use of a graph I was going to have an Edge table that will contain various Coords so that I know, in the image, how to draw my lines. Does this make any more sense to you guys now? Again I apologize, I should've gone a little more into my issue originally.
making a lot of assumptions since your question is vague...
Use two tables with a foreign key, this is the standard approach to model a one to many relationship
create table table1 (
id int
--more columns presumably
)
create table coordinates (
id int,
table_id int --foreign key with table1,
x int,
y int
)
MySQL is a database which, stores data. You can create a table with XCoord and YXoord fields which can handle millions of rows with ease.
CREATE TABLE Coordinates( id int(11) NOT NULL Auto_increment,
X double NOT NULL,
Y double NOT NULL,
PRIMARY KEY (id)
)

Best way to store views / stats in MySQL

I'm working no a site which stores individual page views in a 'views' table:
CREATE TABLE `views` (
`view_id` bigint(16) NOT NULL auto_increment,
`user_id` int(10) NOT NULL,
`user_ip` varchar(15) NOT NULL,
`view_url` varchar(255) NOT NULL,
`view_referrer` varchar(255) NOT NULL,
`view_date` date NOT NULL,
`view_created` int(10) NOT NULL,
PRIMARY KEY (`view_id`),
KEY `view_url` (`view_url`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
It's pretty basic, stores user_id (the user's id on the site), their IP address, the url (without the domain to reduce the size of the table a little), the referral url (not really using that right now and might get rid of it), the date (YYYY-MM-DD format of course), and the unix timestamp of when the view occurred.
The table, of course, is getting rather big (4 million rows at the moment and it's a rather young site) and running queries on it are slow.
For some basic optimization I've now created a 'views_archive' table:
CREATE TABLE `views_archive` (
`archive_id` bigint(16) NOT NULL auto_increment,
`view_url` varchar(255) NOT NULL,
`view_count` smallint(5) NOT NULL,
`view_date` date NOT NULL,
PRIMARY KEY (`archive_id`),
KEY `view_url` (`view_url`),
KEY `view_date` (`view_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
This ignores the user info (and referral url) and stores how many times a url was viewed per day. This is probably how we'll generally want to use the data (how many times a page was viewed on a per day basis) so should make querying pretty quick, but even if I use it to mainly replace the 'views' table (right now I imagine I could show page views by hour for the last week/month or so and then show daily views beyond that and so would only need the 'views' table to contain data from the last week/month) but it's still a large table.
Anyway, long story short, I'm wondering if you can give me any tips on how to best handle the storage of stats/page views in a MySQL site, the goal being to both keep the size of the table(s) in the db as small as possible and still be able to easily (and at least relatively quickly) query the info. I've looked at partitioned tables a little, but the site doesn't have MySQL 5.1 installed. Any other tips or thoughts you could offer would be much appreciated.
You probably want to have a table just for pages, and have the user views have a reference to that table. Another possible optimization would be to have the user IP stored in a different table, perhaps some session table information. That should reduce your query times somewhat. You're on the right track with the archive table; the same optimizations should help that as well.
MySQL's Archive Storage Engine
http://dev.mysql.com/tech-resources/articles/storage-engine.html
It is great for logs, it is quick to write, the one downside is reading is a bit slower. but it is great for log tables.
Assuming your application is a blog and you want to keep track of views for your blog posts, you will probably have a table called blog_posts. In this table, I suggest you create a column called "views" and in this column, you will store a static value of how many views this post has. You will still use the views table, but that will only be utilized to keep track of all the views (and to do checks if they are "unique" or not).
Basically, when a user visits a blog post post, it will check the views table to see if it should be added. If so, it will also increment the "views" field in the corresponding row for the blog post in blog_posts. That way, you can just refer to the "views" field for each post to get a quick peek at how many views it has. You can take this a step further and add redudancy by setting up a CRON job to re-count and verify all the views and update each blog_posts row accordingly at the end of the day. Or if you prefer, you can also perform a re-count on each update if accuracy to-the-second is key.
This solution works well if your site is read-intensive and you are constantly having to get a count of how many views each blog post has (again, assuming that is your application :-))

Categories