PHP: Parse column name values from MySQL query statements? - php

I'm trying to build audit logging for a website. What I want to do is allow existing MySQL queries to go in unchanged (if possible) to a PHP function which parses the data and stores it in the audit log table.
For example, if I have the query
UPDATE members SET name='Bob', age='40' WHERE memberId=123
then I'd like to be able to pull out the table name members, the rowId 123 and both column/data (as if key/value) pairs name:Bob and age:40.
If possible I'd like a solution which also allows for the alternative query format:
UPDATE members (name,age) VALUES ('Bob','40') WHERE memberId=123
These would then go into an audit log table which would look something like this:
+--------+---------+--------+-----+-----------+-----------+
| user | table | column | row | old_value | new_value |
+--------+---------+--------+-----+-----------+-----------+
| admin | members | name | 123 | Joe | Bob |
+--------+---------+--------+-----+-----------+-----------+
| admin | members | age | 123 | 32 | 40 |
+--------+---------+--------+-----+-----------+-----------+
Obviously to populate this table you can see why I need to extract the values. Ideally I'd like to do it from existing MySQL query strings, passed into my PHP function (to handle existing code), but if I need to implement new PHP functions I'm open to suggestions.
Regex seems both complicated and painful since I'd have to format it for each column name for every table. Is there any parsing solution for this problem out there?

Related

Is it possible to reference a MySQL table dynamically?

I can't find anything about dynamically referencing a MySQL table entry in my particular case. Most everything I've read leans towards it not being possible, but I'm hoping someone can prove me wrong.
Essentially, I've got multiple MySQL tables that I'm trying to pull data from on an Android app. I want to access 2 at a time. The 1st Table's name always stays the same, history. The 2nd Table's name, however, may be different at times. It's value is determined within the app and referenced with :job in my php script (I'll use moon for my example). The 2nd table itself is generated dynamically through the app, so I guess I'm trying to set up a reference within a php script I have saved to a server so that I can access the 2nd Table.
Sorry for the confusing description, I hope these tables will help explain what I'm trying to get at.
Table #1: history (always stays the same)
| site | code | hours|
|---------|---------|------|
| moon | first | 1 |
| moon | second | 2 |
| moon | third | 3 |
| earth | fourth | 4 |
Table #2: moon (this one I want to dynamically reference)
| code | hours|
|---------|------|
| first | 10 |
| second | 11 |
| third | 12 |
And my current code:
...
/*** Table #1 ***/
SELECT code,
SUM(hours) AS total, '' AS target
FROM history
WHERE site = :job /* :job ends up being moon in this example */
GROUP BY code
UNION ALL
/*** Table #2 ***/
SELECT code,
'' AS total, SUM(hours) AS target
FROM :job /* <--- I'm trying to do something along these lines and use 'moon', or 'earth', or whatever... */
GROUP BY code
...
And later I get :job from the app: (moon)
$query_params = array(
':job' => $_POST['jobname'],
);
Result I'm Looking For: (works perfect if I directly use Table #2's name (ie moon) in my php file)
| code | hours|target|
|---------|------|------|
| first | 1 | 10 |
| second | 2 | 11 |
| third | 3 | 12 |
The code absolutely works as expected when I replace the :job in the 2nd table with the actual name of the table. I'm wondering if there is some way to still do it dynamically though?
Thanks for any and all advice!
I've done some pretty extensive searching and haven't come up with anything that works for me.
Is it possible to reference a mysql table entry value from a second table entry dynamically?
https://dev.mysql.com/doc/refman/5.7/en/derived-tables.html
MySQL table.* AS reference
Retrieve parent-child hierarchy from a self-referencing mysql table

PHP: prevent duplicated tags in Mysql

I have MySql Table For Tags Like This:
| id | name |
| 1 | Linux |
| 2 | Windows |
| 3 | Unix |
| 4 | Dos |
| 5 | FreeBSD |
In News Page User add New Tags Like This:
Linux,OpenBSD,Test
Now, Linux Previously added, So I need To add ONLY OpenBSD and Test Into Tags Table. My Mean Is: how to INSERT tags if User tags is New?!
Put a UNIQUE constraint on the name column.
Use INSERT IGNORE so that inserting a column where name already exists simply skips that row. eg:
INSERT IGNORE INTO tags (name) VALUES ('Linux'), ('OpenBSD'), ('Test');
Because you have different casings in your data [eg: linux vs Linux] you either need to make sure that you are using a case-insensitive coallation in your database like utf8_latin1_ci [ci stands for case-insensitive] or be sure to use strtolower() on your data prior to inserting it.
Like Jay suggested, normalise the data, then make the column UNIQUE, and use something like INSERT IGNORE INTO yourTags(name) VALUES(?),(?),(?) (and send in the three values as parameters). I'm also assuming that the ID column is AUTO INCREMENT.

PHP and MySQL average

I have this structure in table named grades
1st row: 2nd row:
------------------------------
| english | math |
------------------------------
| 3 | 4 |
| 4 | 4 |
| 5 | 2 |
| 2 | 5 |
------------------------------
How do I now calucate average of english row?
I tried with:
"SELECT AVG(english) as `averageenglish` FROM grades"
It always gives me "No database selected"
Database selections are per session. If you go into the MySQL command prompt and type
USE MyDatabase
you do not have to qualify table names in queries for that session. As soon as you leave (exit, Ctrl+c, etc.) you don't have that privilege. You will have to USE the database again or qualify table names in queries. This includes a session created by a separate script that is not running on the command line.
In production code, it is helpful to always qualify table names in queries. Your query should look like:
SELECT AVG(english) as averageenglish FROM MyDatabase.grades
To demonstrated what #eggyal means
SELECT AVG(english) as `averageenglish` FROM databasename.grades
The preferred method is to add the database name to your connection if you only have one database.

PageViews, Dynamic Page visits counter similar to Google Analytics or Alexa?

I want to put a hit counter or visits to display for my website http://www.deerpages.co on every dynamic pages. I'm using Php and MySQL. But, I'm thinking of once I've put every tracking in per row inserted, then that table will be full soon.
Is there any external ways we can do this? I mean, like Google Analytics or Alexa type of trackings? and can be able to display them?
Any help would be appreciated.
Thanks a lot!
When you put a page counter on content, you change the value of the counter in your database, not insert a new row for it each time.
Assuming your table looks something like this:
contentTable
+------+---------+
| ID | Counter |
|------|---------|
| 1 | 35 |
| 2 | 54 |
+------+---------+
You can update the row with ID of 1 like this:
update contentTable set Counter=Counter+1 where ID=1;
Assuming that you link each page to an ID in the database. You can also easily keep all your content in the same database table.
Edit:
If you want to store other data about each visitor, then make a separate hitCounter table along the following lines:
CounterTable
+----+---------+----------+---------|
| ID | Counter | HTTP_REf | Country |
|----+---------+----------+---------|
| 1 | 46 | SomeData | USA |
| 2 | 28 | Data2 | Aus |
+----+---------+----------+---------+
And update the data as required based on the users individual data columnsm such as:
insert into counterTable (ID, Counter, HTTP_Ref, Country)
values (null, 1, '".$HTTP_REF."', '".$country."')
On Duplicate Key update set counter=counter+1;
(Assuming Keys of ID, HTTP_Ref and Country)
Having said that, I would suggest either looking at using some space on the database (really, you will need a LOT of hits to "fill up the tables" as such) or maybe simply split the basic counter with a stats table that lists Country, Referrer and the like into different tables.

Creating a MySQL table upon user registration

I am developing a website which will collect and store information for users.
I need to create a table specific to each individual user on registration to store the information they are searching for using the website. The table created will be named after the newly registered user's username.
Then when the user is logged in and runs the search, the data collected will be stored in a database using a MySQL insert query where the table name is a variable containing the logged-in user's username which will also be the table name.
I am an amateur developer and have searched everywhere to try and find a solution but I cannot seem to find anything evenly remotely similar to my problem.
Thank you in advance for any help!
Creating tables on the fly is more trouble than it's worth and very much swimming against the tide with any SQL database.
The reason you haven't found any docs about the approach you mention is because this problem is generally (almost without exception) solved best by having all the data in one or more tables, and including a column to specify which entity (user) the row is associated with. In your case, this might be an email address, or a username, or just a sequential number.
E.g.
| user_id | email | first_name | last_name | fave_color |
- - - - - -
| 1 | "a#b.c" | "anton" | "aardvark" | "red" |
| 2 | "b#c.d" | "miles" | "o'brien" | "infrared" |
| ... | | | | |
First take name from user like:
$fullname="$fname"."_"."$lname";
Then, write a query like this to create a table of that name
$sql="CREATE TABLE $fullname(ALL THE COLLUMNS YOU WANT TO CREATE)";
$result1=mysql_query($sql, $db_link);
this query is from my project. Works fine in wampserver.

Categories