I'm developing a webaplicattion in php where there will be an area called 'My Products'. This area you can see the products that you listed. Lets say you placed a car to sell. You will have something like:
Model: R8
Color: Yellow
Brand: Audi
Type: Diesel
Price: 90000
CarID: 1
My problem: How can I select the carid so that I have the cardid as the key and the other values (eg. model, color, etc...) as values?
I'm using mysql to store the listings. SQL TABLE:
+---------+------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------------------------------+------+-----+---------+----------------+
| carid | int(11) | NO | MUL | NULL | auto_increment |
| brand | enum('Alfa Romeo','Aston Martin','Audi') | NO | | NULL | |
| color | varchar(20) | NO | | NULL | |
| type | enum('gasoline','diesel','eletric') | YES | | NULL | |
| price | mediumint(8) unsigned | YES | | NULL | |
| mileage | mediumint(8) unsigned | YES | | NULL | |
| model | text | YES | | NULL | |
| year | year(4) | YES | | NULL | |
| user | varchar(30) | YES | | NULL | |
+---------+------------------------------------------+------+-----+---------+----------------+
My pseudo code is something like this:
Fetch ID of the cars that was listed by certain user;
Use that ID as a key;
Get every other options to be the values (diesel, yellow, etc...)
I have tried some codes since array_combine to foreach inside foreach.
This is the code I have ended up so far:
$qry_id = "select carid from cars where user='$login'";
if ($car_id = mysqli_query($link, $qry_id)){
while ($row = mysqli_fetch_assoc($car_id)){
//It will fetch the iD of the user in the DB
$user_id = $row["carid"];
$qry_model = "select model from cars where carid='$user_id'";
if($model_obj = mysqli_query($link, $qry_model)){
while ($row_2 = mysqli_fetch_assoc($model_obj)){
$model = $row_2['model'];
$final_array = array($user_id => $model);
}
}
}
}
I don't know if this is the right approach since it's my first webapp I'm building.
I'm just using the model value in this code for the simplicity sakes.
$q = "SELECT * FROM cars where user=?";
if ($stmt = $pdo->preapre($q)){
$result=[];
$stmt->execute([$login]);
while ($row = $stmt->fetchObject()){
$carId = $row->carid;
unset($row->carid);
$result[$carId]=$row;
}
}
now note that $pdo is object of pdo connecttion to the database not mysqli, you can do the same thing with mysqli but i am not uses to it
also i don't recommend that you use the user name on every column you should instead store the userId as foreign key to the primary key id in the table user
that will save alot more storage make the query faster ( it's easier to look for numbers than string ) and user can change it's name without having to change his name in all other tables ( userid won't be changing of course )
also carid should be unsigned int(10) not int(11) if wondering why 10 see that post MySQL datatype INT(11) whereas UNSIGNED INT(10)?
To avoid SQL injection, use prepared statements. You can use one query to fetch all attributes for the cars:
$qry_id = "select carid, model, price, color from cars where user=?";
$stmt = mysqli_prepare($link , $qry_d) or die("SQL statement error");
// Bind the login parameter to the statement
mysqli_stmt_bind_param($stmt, "s", $login);
mysqli_stmt_execute($stmt);
// bind every column in the SELECT
mysqli_stmt_bind_result($stmt, $user_id, $carid, $model, $price, $color);
while (mysqli_stmt_fetch($stmt)){
$final_array[] = array(
"model" => $model,
"price" => $price,
"color" => $color
);
}
You may do the following
Note this query is not safe and pron to SQL Injection, I would recommend to use prepared statements or PDO
The $carArray variable will finally have the array with carid as key in it
$query = "select * from cars where user='$login'";
$result = mysqli_query($query);
$carArray = array();
while ($row = mysqli_fetch_assoc($result)){
$carArray[$row['carid']] = $row;
}
Related
So I have a query that gets all the posts in the database. Say I post a post, it won't show, till I post another post. So essentially there's a post delay, until you post another post. That's the best I can explain it. Here's my query
SELECT * FROM comments WHERE comment_post_id = :id
Then I create an array
//Get post comments
$cmt = $con->prepare("SELECT * FROM comments WHERE comment_post_id = :id");
$cmt->bindValue(':id', $id, PDO::PARAM_INT);
$cmt->execute();
$cmtc = $cmt->fetch(PDO::FETCH_ASSOC);
$comments = array();
while($row = $cmt->fetch(PDO::FETCH_ASSOC)){
$comments[] = array(
'comment_user' => $row['comment_user'],
'comment_ip' => $row['comment_ip'],
'comment_date' => $row['comment_date'],
'comment_content' => $row['comment_content'],
'comment_post_id' => $row['comment_post_id']
);
}
And finally display it
<?php foreach($comments as $comment){?>
<h1 class="message"><?php echo $comment['comment_content']?></h1>
<?php } ?>
I'm not getting any errors, but when I run the query in the command line I get one result. But when I visit the page I don't see any results.
Here's the structure
+-----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| comment_user | varchar(255) | YES | | NULL | |
| comment_ip | varchar(255) | YES | | NULL | |
| comment_date | varchar(255) | YES | | NULL | |
| comment_content | varchar(85) | YES | | NULL | |
| comment_post_id | varchar(255) | YES | | NULL | |
+-----------------+------------------+------+-----+---------+----------------+
Your first call to fetch automatically increments the internal pointer of the result set by one after fetching the row:
$cmtc = $cmt->fetch(PDO::FETCH_ASSOC);
The above returns the zeroth row and moves the pointer to the first row. So, when you get to your while loop, the pointer is offest by one, and nothing is found:
while($row = $cmt->fetch(PDO::FETCH_ASSOC)){
The reason is that line:
$cmtc = $cmt->fetch(PDO::FETCH_ASSOC);
You should simple remove it.
Otherwise you fetch first record and don't assign it to $comments variable and then in loop you try to get records from 2 to n
To fetch all results of your query try this:
$cmt = $con->prepare("SELECT * FROM comments WHERE id = :id");
$cmt->bindValue(':id', 1);
$cmt->execute();
$comments = $cmt->fetchAll(PDO::FETCH_ASSOC);
PS. your schema use id as primary key, but your query use comment_post_id.
I'm trying to update values in a table that looks like this:
+----+-------------+
| Id | Value |
+----+-------------+
| 1 | title |
+----+-------------+
| 2 | description |
+----+-------------+
| 3 | email |
+----+-------------+
| 4 | keywords |
+----+-------------+
I would like to update the value if the PK already exists, otherwise insert a new row.
submit.php:
include('../../include/config.php');
if($_POST['settings']){
$title=$_POST['title'];
$description=$_POST['description'];
$email=$_POST['email'];
$keywords=$_POST['keywords'];
$test=$db->query("UPDATE `settings` SET `value` = '$title' WHERE `id` =1, SET `value` = '$description' WHERE `id` =2,SET `value` = '$email' WHERE `id` =3, SET `value` = '$keywords' WHERE `id` =4;");
if($test){
echo "good";
}else{
echo "bad";
}
}
UPDATE:
To whoever reading this question now, don't use this structure to store your website settings. and I don't recommend using the query either because it is vulnerable to SQL injection
Consider this example...
SELECT * FROM user;
+---------+------+
| user_id | name |
+---------+------+
| 1 | X |
| 2 | B |
| 3 | C |
+---------+------+
UPDATE user
SET name = CASE user_id WHEN 1 THEN 'A'
WHEN 2 THEN 'J'
WHEN 3 THEN 'K' END;
SELECT * FROM user;
+---------+------+
| user_id | name |
+---------+------+
| 1 | A |
| 2 | J |
| 3 | K |
+---------+------+
This query can in fact be done with a single statement in Mysql as long as you have a unique index or primary key on your Id field.
INSERT INTO `settings` (`id`,`value`) VALUES (1,?),(2,?),(3,?),(4,?)
ON DUPLICATE KEY UPDATE `value`=VALUES(`value`);
See the documentation of INSERT ... ON DUPLICATE KEY at https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
I'm currently working on a "news feed" type of script and I am trying to load the posts created by the user's friends. My current code partially works; it only loads from one friend and finishes. What am I doing wrong?
<?php
$infofriends = mysql_fetch_array(mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"));
$infofrnd = mysql_fetch_array(mysql_query("SELECT * FROM btaccs WHERE `auto`='".$infofriends['friend_id']."'"));
$posts = mysql_query("SELECT * FROM btpost WHERE `user`='".$infofrnd['user']."' ORDER BY `auto` DESC") or die('Error: '.mysql_error());
while($row = mysql_fetch_array( $posts )) {
$infobeer = mysql_fetch_array(mysql_query("SELECT * FROM btbeer WHERE `beer`='".$row['beer']."'"));
$infouser = mysql_fetch_array(mysql_query("SELECT * FROM btaccs WHERE `user`='".$row['user']."'"));
....
(Currently sloppy, I'll be editing that afterwards).
MySQL structures:
btfriend
mysql> DESCRIBE btfriend;
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| auto | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | | NULL | |
| friend_id | int(11) | YES | | NULL | |
+-----------+---------+------+-----+---------+----------------+
btaccs
mysql> DESCRIBE btaccs;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| auto | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(150) | YES | | NULL | |
| display | varchar(150) | YES | | NULL | |
| pass | varchar(250) | YES | | NULL | |
| email | varchar(150) | YES | | NULL | |
| firstname | varchar(150) | YES | | NULL | |
| lastname | varchar(150) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
btpost
mysql> DESCRIBE btpost;
+---------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------------+------+-----+---------+----------------+
| auto | int(11) | NO | PRI | NULL | auto_increment |
| user | varchar(500) | YES | | NULL | |
| beer | varchar(911) | YES | | NULL | |
| img | varchar(30) | YES | | NULL | |
| rate | varchar(10) | YES | | NULL | |
| loc | varchar(1000) | YES | | NULL | |
| comment | varchar(1500) | YES | | NULL | |
| fb | varchar(10) | YES | | NULL | |
| type | int(2) | YES | | NULL | |
+---------+---------------+------+-----+---------+----------------+
It'd be great if someone could help!
First of all, you're using mysql_* functions; those have been deprecated, and will stop working at some point in the future. Look at switching to mysqli_ or PDO instead - they both make it easier to write safer code.
Secondly, you're calling your code in such a way that you're expecting it to work:
$infofriends = mysql_fetch_array(mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"));
If the query fails, you'll be passing a boolean false to mysql_fetch_array; it's a lot easier to make each statement one at a time, and handle errors as they come up:
$friendset = mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'") or die (mysql_error());
$infofriends = mysql_fetch_array($friendset) or die (mysql_error());
That will generate an error on the appropriate line if something goes wrong - it's a little more code, but it's much easier to debug and maintain.
Finally, your actual question; you're only getting one friend, because you're only calling mysql_fetch_array() once on the friend query; that will return to the top row. A quick solution would be to loop through the results separately to generate a list, and then pass that into the second query:
$friendset = mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'") or die (mysql_error());
$friendArray = array();
while ($infofriends = mysql_fetch_array($friendset)) {
$friendArray[] = $infofriends['friend_id'];
}
$friendArray[] = $infousr['auto'];
// At this point, you have an array of friend IDs.
$posts = mysql_query("SELECT * FROM btpost INNER JOIN btaccs ON btpost.user=btaccs.user WHERE btaccs.auto IN (" . implode(',', $friendArray) . ") ORDER BY btpost.auto DESC") or die('Error: '.mysql_error());
Note that it's using an IN to retrieve all the IDs at once; you might want to add an extra parameter to the ORDER BY to arrange the posts by friend.
Note that I've not tested this, so there may be issues with the syntax, but I hope it's enough for you to get the general idea.
--
We solved this in the chat and have added $friendArray[] = $infousr['auto']; which would also include the posts from the current user. The current user's ID, along with the friend IDs, would then go into the implode function in the query. We also linked the btpost and btaccs tables because btaccs held the user's ID, while btpost held the username. Full chat transcript -alexpja
Try this with using single query with join
SELECT p.*
FROM btpost p
INNER JOIN btfriend f ON (p.`user` = f.friend_id)
WHERE f.user_id =$infousr['auto']
Then loop through all the results from query,this will give you all the posts where btpost's user is equal to the friend's id btfriend and these are the friends of your given user id $infousr['auto'] I assume $infousr['auto'] will have the user id
I think you're missing a loop. Let's break down your code:
<?php
// Here, you run a query that presumably returns multiple rows, but you're only looking at the first row:
$infofriends = mysql_fetch_array(mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"));
// That gave you a single array of the first friend that MySQL found
// Now, you take the `friend_id` field from that single result, and you run it against the `btaccs` table to get some more information:
$infofrnd = mysql_fetch_array(mysql_query("SELECT * FROM btaccs WHERE `auto`='".$infofriends['friend_id']."'"));
// Once again, you have a single row at this point. (Although here, I'm assuming that's ok, since a user's ID probably appears only once in this table
// Now, you take the single user that you've looked up, and you find posts associated with that user:
$posts = mysql_query("SELECT * FROM btpost WHERE `user`='".$infofrnd['user']."' ORDER BY `auto` DESC") or die('Error: '.mysql_error());
I think you can see that it's the first statement that limits it to a single user. Try creating an array before running that statement, and then looping through your result set, adding to that array.
A few other things I'd seriously consider:
1) Take advantage of PHP's double-quote string substitution...
mysql_query("SELECT * FROM btfriend WHERE `user_id`='{$infousr['auto']}'"
is a little easier to read than
mysql_query("SELECT * FROM btfriend WHERE `user_id`='".$infousr['auto']."'"
2) Read up on JOINs in MySQL. Everything you've done here can actually be collapsed into a single query in MySQL. It'd be a little too much to go into detail here, but you can start with the MySQL docs: http://dev.mysql.com/doc/refman/5.0/en/join.html
I am currently trying to build a form using mysql/php, below is part of the code I have so far
BLOCK#1:
$proceso = mysqli_fetch_assoc($result); // my query returns only one row
...
<form action='actualizar.php' method='Post'>
<?php
foreach(array_keys($proceso) as $key){
echo "<label for='$key'>$key: </label>";
echo "<input name='$key' value='".$proceso[$key]."'><br/>";
}
echo "<input type='hidden' name='View' value='$view'>";
?>
<input type="submit" value="Actualizar">
</form>
This so far is getting me a form where I'm using the field names to generate labels and input boxes where i show the field value. I would like to further format some of the fields using the jquery datepicker, but only for those fields which have a type = Date in the mysql table.
I've been trying mysqli_fetch_field_direct using something like:
BLOCK#2:
$fields = mysqli_num_fields($result);
for ($i=0; $i < $fields; $i++) {
$field_types[] = $result->fetch_field_direct($i)->type;
}
but in this case I can't get the value, just the type
Is there a straightforward way to get the type and value of a field?
Edited to (try) to simplify:
Let's say I have a field called email which has type = varchar and my SQL query generates one result test#example.com
From BLOCK#1 I get:
-------------------------------
Field-Name | Field-Value
email | test#example.com
From BLOCK#2 I get:
-------------------------------
Field-Name | Field-Type
email | varchar
what I would like is to get
-------------------------------
Field-Name | Field-Type | Field-Value
email | varchar | test#example.com
This is because I would like to use the field type to add a css class to the input box (such as to use the datepicker).
Edit: I put the output in a table because I can't sleep...
Okay... see if this is what you want...
This is a table I made for a different SO question:
mysql> describe user;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| User_ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| Email | varchar(100) | YES | | NULL | |
| Name | varchar(100) | YES | | NULL | |
| Password | varchar(100) | YES | | NULL | |
| FB_ID | int(11) | YES | | NULL | |
| Total_Score | int(11) | YES | | 0 | |
| add_date | datetime | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
and from the DB:
mysql> select * from user limit 1;
+---------+-------+------+----------+-------+-------------+---------------------+
| User_ID | Email | Name | Password | FB_ID | Total_Score | add_date |
+---------+-------+------+----------+-------+-------------+---------------------+
| 1 | NULL | kim | NULL | NULL | 10 | 2013-11-03 23:04:08 |
+---------+-------+------+----------+-------+-------------+---------------------+
+
1 row in set (0.00 sec)
And the code:
<?php
$mysqli = mysqli_connect("localhost", "root", "", "test");
// this came from http://php.net/manual/en/mysqli-result.fetch-field-direct.php
$mysql_data_type_hash = array(
1=>'tinyint',
2=>'smallint',
3=>'int',
4=>'float',
5=>'double',
7=>'timestamp',
8=>'bigint',
9=>'mediumint',
10=>'date',
11=>'time',
12=>'datetime',
13=>'year',
16=>'bit',
//252 is currently mapped to all text and blob types (MySQL 5.0.51a)
253=>'varchar',
254=>'char',
246=>'decimal'
);
// run the query...
$result = $mysqli->query("select * from user limit 1");
// get one row of data from the query results
$proceso = mysqli_fetch_assoc($result);
print "<table>
<tr>
<th>\$key</th>
<th>\$value</th>
<th>\$datatype</th>
<th>\$dt_str</th>
</tr> ";
// to count columns for fetch_field_direct()
$count = 0;
// foreach column in that row...
foreach ($proceso as $key => $value)
{
$datatype = $result->fetch_field_direct($count)->type;
$dt_str = $mysql_data_type_hash[$datatype];
$value = (empty($value)) ? 'null' : $value;
print "<tr>
<td>$key</td>
<td>$value</td>
<td class='right'>$datatype</td>
<td>$dt_str</td>
</tr> ";
$count++;
}
print "</table>";
mysqli_close($mysqli);
?>
<style>
/* this is css that you don't need but i was bored so i made it pretty...! */
table { font-family:Courier New;
border-color:#E5E8E3; border-style:solid; border-weight:1px; border-collapse:collapse;}
td,th { padding-left:5px; padding-right:5px; margin-right:20px;
border-color:#E5E8E3; border-style:solid; border-weight:1px; }
.right { text-align:right }
</style>
So... to clarify...
You can use these variables in that foreach to output or use the information however you want: (I am using my first row of output, for the user_id, as an example)
$key is the column/field name (such as user_id)
$field_types[$key] comes from $result->fetch_field_direct($i)->type (such as 3)
$mysql_data_type_hash[$datatype] is the string version of the datatype using the $mysql_data_type_hash array at the top of the code. This isn't necessary but I included it so this example is more clear. (such as int)
$proceso[$key] = $value = is your value for this iteration of the foreach statement (such as 1)
Output:
$key $value $datatype $dt_str
User_ID 1 3 int
Email null 253 varchar
Name kim 253 varchar
Password null 253 varchar
FB_ID null 3 int
Total_Score 10 3 int
add_date 2013-11-03 23:04:08 12 datetime
i am trying to build a system that logs, media (photo, video, audio) upload statistic. so i come up with 3 tables, 1 for audio, 1 for video, and 1 for photo. and here's the structure
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| member_id | int(10) | NO | | NULL | |
| counter | int(11) | NO | | NULL | |
| daydate | text | NO | | NULL | |
| epochtime | text | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
all three tables has the same fields, since i think (so far) i need to differentiate the medias on each and particular table, is this redundant ??
anyway since each of the media is treated the same, so i think i should only build once class and kinda use the methods depending of what media i am accessing at the time. here's the class :
require_once(INC_PATH.DS.'database.php');
class Log extends DatabaseObject {
protected static $db_fields = array('id', 'member_id', 'counter', 'daydate', 'epochtime');
public $id;
public $member_id;
public $counter;
public $daydate;
public $epochtime;
public function find_counter($table_name){
global $database;
$time = date('d-m-Y');
$timestamp = time();
$sql = "SELECT * FROM ". $table_name;
$sql .= " WHERE daydate = '".$this->daydate."'";
$sql .= " AND member_id = '".$this->member_id."'";
return self::find_by_sql($sql);
}
public function add_log($table_name){
global $database;
$tes = $this->find_counter();
if(!empty($tes)){
$sql = "UPDATE ".$table_name;
$sql .= " SET counter = counter+1";
$sql .= " WHERE daydate = '".$this->daydate."'";
$sql .= " AND member_id = '".$this->member_id."'";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}else{
$sql = "INSERT INTO ".$table_name;
$sql .= " (id, member_id, user_privelege, counter, daydate, epochtime)";
$sql .= " VALUES ('', '".$this->member_id."'";
$sql .= " , '".$this->user_privelege."', '1', '".$this->daydate."', '".$this->epochtime;
$sql .= "')";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
}
}
so far this is pretty much working but, i still have doubts on the way i break the table in to 3 tables, and the way i use the $table_name as parameter. any suggestions for better approach ?? i really want to improve my codes, thank you very much
Regards
UPDATE
alright, based on everybody's answer, i would like to clear somethings up:
i only need to log the uploaded media
i already have another separate table to record other information (length, filename, titles, etc) for each media.
lets just say i add a field called "media_id" and merge the table into one, and since the way that i add and update my rows is based on the day-date, it will INSERT if the given daydate and the member_id is not found, and otherwise it will UPDATE, i think i should also change the way my add_log() method works, into something like:
public function add_log($table_name, $media_id){
global $database;
$tes = $this->find_counter();
if(!empty($tes)){
$sql = "UPDATE ".$table_name;
$sql .= " SET counter = counter+1";
$sql .= " WHERE daydate = '".$this->daydate."'";
$sql .= " AND member_id = '".$this->member_id."'";
$sql .= " AND media_id = '".$media_id."'";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}else{
$sql = "INSERT INTO ".$table_name;
$sql .= " (id, member_id, media_id, counter, daydate, epochtime)";
$sql .= " VALUES ('', '".$this->member_id."'";
$sql .= " , '".$media_id."', '1', '".$this->daydate."', '".$this->epochtime;
$sql .= "')";
$database->query($sql);
return ($database->affected_rows() == 1) ? true : false;
}
}
what do you guys think ??
thanks again
Put it all in one table and have a media_type column.
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| member_id | int(10) | NO | | NULL | |
| counter | int(11) | NO | | NULL | |
| daydate | text | NO | | NULL | |
| epochtime | text | NO | | NULL | |
| media_type| int | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
Create a foreign key relationship to another table that defines media_type.
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| media_type_id| int | NO | PRI | NULL | |
| description | text | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
This would hold media_type_id (e.g. 1) and media_type_description (e.g. audio).
e.g.
1, audio
2, video
3, photo
The main table would then just include on each row the id of 1, 2, 3 to denote which media type it is. You can then use this from your application to constrain via the WHERE clause, which media you're referring to. e.g. SELECT * FROM maintable WHERE media_type_id = 3 to just get the photos.
Make it one table with an extra column "media_type". Your design would require you to make an extra table for every new media type and that is possibly poor design.