Uploading data into two mysql tables - php

i have a problem where i have two tables in a database, one being categories (cat_id and cat name) and the other being jokes (joke_id and joke). I want a user to be able to chose a category and describe their joke, then this being entered into the database with the category of the joke being referenced so the joke can be portrayed on a specific category page. So far i am able to upload the joke to the database but yet i have not been able to upload the joke to a specific category.
here is the code to the joke table
CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(51) NOT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
the code for the joke table
CREATE TABLE `jokes` (
`joke_id` int(11) NOT NULL AUTO_INCREMENT,
`joke` varchar(1024) NOT NULL,
PRIMARY KEY (`joke_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
and this peiece of code inserts the joke description to the joke table
if ($valid) {
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO jokes (joke) values(?)";
$q = $pdo->prepare($sql);
$q->execute(array($joke));
Database::disconnect();
header("Location: index.php");
}
i am not sure how to upload data into the other table, with the joke being assigned a category. If anybody could help me that would be fantastic, thank you.
Here is the full file on githut: https://github.com/sambarrowclough/jokes.git

I suspect you're looking for a way to somehow connect the joke with a given category. Well, that's what R stands for in RDBMS, so I would advice to do some research on "relationships" between MySql tables. I think that useful will be also concepts such as foreign key and perhaps joining tables afterwards.
But if you're looking just for quick solution, you can define your jokes table as following:
CREATE TABLE `jokes` (
`joke_id` int(11) NOT NULL AUTO_INCREMENT,
`joke` varchar(1024) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`joke_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
The above doesn't add foreign key restriction but requires the category to be set (as being NOT NULL). Nevertheless, it allows you to add the new entity to database this way:
$sql = "INSERT INTO jokes (joke, category_id) values(?,?)";
$q = $pdo->prepare($sql);
$q->execute(array($joke, $category_id));
where $category_id is expected to stand for id of category the joke belongs to.

In order to link the joke to the category, you need to add correspond field in jokes table.
CREATE TABLE `jokes` (
`joke_id` int(11) NOT NULL AUTO_INCREMENT,
`joke` varchar(1024) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`joke_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5;
And then:
$category_id = $_POST['category_id'];
if ($valid) {
$pdo = Database::connect();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO jokes (joke, category_id) values(?,?)";
$q = $pdo->prepare($sql);
$q->execute(array($joke, $category_id));
Database::disconnect();
header("Location: index.php");
}
category_id will show which category is applied to the joke, so you will be able retrieve correspond category info from categories table.

You can't add a joke in the category table. You have to reference the category with an indexed field in your table :
+=============+ +=============+
| category | | jokes |
+=============+ +=============+
| category_id | | joke_id |
+-------------+ +-------------+
| name | | joke |
+-------------+ +-------------+
| category_id |
+-------------+
Then when you retrieve a joke, you know to which category it belongs.
This is really basic in database disigning. You should learn a bit more on database relationships.
Don't forget to create an index on the field (for huge performance gains) :
CREATE INDEX "idx_category" ON "jokes" (category_id);

Related

How can I make categories for all the posts?

I am trying to learn and understand PHP and MySQL. I decided to make a small project and learn as I progress.
Now I have my DB something like this (ill try to keep it clean without all fields):
users
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL,
articles
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
body TEXT NOT NULL
To display all articles I used PHP PDO
$sql = 'SELECT * FROM articles';
$query = $db->prepare($query);
$query->execute();
$articles = $query->fetchAll();
And to display single article I created new article.php page and went with this
$id = $_GET['id'];
$sql = 'SELECT * FROM articles WHERE id = :id';
$query = $db->prepare($sql);
$query->execute(['id' => $id]);
$article = $query->fetch();
And id is from index page something like this
<a href="<?php echo ROOT_URL ?>article.php?id=<?php echo $article['id'];?>Read Post</a>
Far as it goes by now everything works fine but my first question is how can I make categories for all the post. I had in mind making a new table and altering articles table by adding FOREIGN KEY:
articles
FOREGEIN KEY (cat_id) REFERENCES categories(id)
ON DELETE CASCADE ON UPDATE CASCADE
categories
id INT NOT NULL AUTO INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
But now I don't know exectly how to make query to get all articles with same category similar to article.php where it would be category.php instead.
And my second question is what query should I use to enable users to leave comments on article. I have idea how table needs to look
comments
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
body varchar(255) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE ON UPDATE CASCADE
FOREIGN KEY (post_id) REFERENCES posts(id)
ON DELETE CASCADE ON UPDATE CASCADE
And I wrote something like this
if (isset($_POST['comment'])) {
$body = $_POST['body'];
$article_id = $_POST['article_id'];
$user_id = $_SESSION['id'];
$sql = "INSERT INTO comments(user_id, article_id, body) VALUES (:user_id, :article_id, :body)";
$query = $db->prepare($sql);
$query->execute(['user_id' => $user_id, 'article_id' => $article_id, 'body' => $body]);
}
<input type="hidden" name="article_id" value="<?php echo $article['id'] ?>">
<button type="submit" name="comment">Leave a Comment</button>
But comments went on all of the articles.
how to make query to get all articles with same category similair to article.php where it would be category.php instead
It's literally the same thing, just the names change:
SELECT *
FROM articles
WHERE cat_id = :cat_id
However, I think sooner or later you'll need to join tables, which is the core feature of relational databases (sadly, there're many developers who think that SELECT * FROM tablename is all the SQL you'll every need). In this case, you can do something like this:
SELECT cat.id AS cat_id, cat.name AS cat_name, art.id AS art_id, art.body
FROM categories cat
INNER JOIN articles art ON cat.id = art.cat_id
WHERE cat.id = :cat_id
ORDER BY art.id DESC
There's a classic article that explains this pretty nicely: A Visual Explanation of SQL Joins
what query should I use to enable users to leave comments on article
You don't really way where you're stuck but it's basically the same story (same query, different names):
SELECT *
FROM comments
WHERE post_id = :post_id
Finally, two random tips:
I would not set ON DELETE CASCADE for articles.cat_id. I don't see much real life usage for batch removing articles by category and it makes easy to do it by mistake.
Try to make your naming consistent. You only have 4 entities and you're already using different terms for the same stuff (category vs cat, article vs post).
If you want to select all articles, which one is in some category. You can do something like this.
$id = $_GET['category_id'];
$sql = 'SELECT * FROM articles WHERE cat_id = :id';
$query = $db->prepare($sql);
$query->execute(['id' => $id]);
foreach($query->fetchAll() as $results){
// Here you can make a magic.
echo '<h2>' . $results['Article_Name'] . '</h2>';
print_r($results);
}
The same principle you can do with comments. Just to make a query on every article page.
Like this one for example.
SELECT * FROM comments WHERE article_id = :article_id
Mysql tables example:
CREATE TABLE IF NOT EXISTS `articles` (
`id` bigint(22) NOT NULL AUTO_INCREMENT,
`userid` bigint(22) NOT NULL DEFAULT 0,
`catid` bigint(22) NOT NULL DEFAULT 0,
`title` varchar(190) NOT NULL DEFAULT '',
`text` text,
`active` int(1) NOT NULL DEFAULT 1,
`ban` int(3) NOT NULL DEFAULT 0,
`ip` varchar(200) NOT NULL DEFAULT '',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `ukey` (`userid`,`title`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `categories` (
`id` bigint(22) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`slug` varchar(50) NOT NULL,
`active` int(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `ukey` (`slug`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
// Add first category (after this id = 1 for example)
INSERT INTO categories(name,slug) VALUES('Category 1', 'cat1-slug')
// Here userid == logged user id
// Here: catid == id field from categories table (category id from categories table)
INSERT INTO articles(userid,catid,title,text) VALUES(1,1,'Article title','Article content')
Select articles with category name (mysql join)
SELECT articles.*,categories.name,categories.slug,categories.id as catid from articles LEFT JOIN categories ON articles.catid = categories.id WHERE articles.active = 1 AND articles.catid = 1
Don't use it, it's not needed:
FOREGEIN KEY (cat_id) REFERENCES categories(id)
ON DELETE CASCADE ON UPDATE CASCADE

MYSQL will not return more than 1 category

I've tried to find an answer to this problem, but I can't.
I have a 3 table format mqsql database.
I use 1 table to add all of the product information, CarpetInfo,
1 Table to list my categories, CarpetCategories,
and 1 Table to add categories to the products, CarpetCategorySort.
My CarpetCategorySort table has 3 columns, Manufacturer, Style, CategoryID.
Example would be Manufacturer = Aladdin, Style = Alma Mater, CategoryID = 14/ 15/ 18/ 19/ 20/ 21/ 67/
My CarpetCategories Table has 2 Columns CategoryID and Category.
2 Examples would be CategoryID = 14, Category = Commercial &
CategoryID = 15, Category = Commercial Loop
I can only get the code to work when I type in Commercial into the $category variable below. The code will not work if I type Commercial Loop into the $category variable. It's like it will only pull in the first number 14 and all of the others are ignored. The pricing order and everything else works right, just not the CategoryID part.
Here is my code.
<?php $mill = "Aladdin"; $category = "Commercial Loop";
$order = mysqli_query($con, "
SELECT * FROM CarpetInfo JOIN CarpetCategorySort USING (Manufacturer, Style)
JOIN CarpetCategories USING (CategoryID)
WHERE Manufacturer='$mill' AND Category LIKE '%$category%'
order by Price = 0, Price asc,
Style asc");
include($_SERVER['DOCUMENT_ROOT'].'/includes/pricing/carpet-order-test.htm');?>
Any help is greatly appreciated!
That's a backward way of handling things, a field with several datapoints smooshed together like that really never has any justification for existence. I'd list the carpets in one table, list the categories in another, and finally list cross-references of both in another table, where you get a many-to-one relationship at both ends.
You need an actual category table only if you think it's going to take so much room to give duplicate info for each category and/or you can't control user input for categories (like you aren't just using a pulldown to give a name choice).
Something like:
CREATE TABLE IF NOT EXISTS `carpets` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`abbrev` varchar(10),
`description` varchar(250),
[...]
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `carpet_categories` (
`id` int(11) NOT NULL,
`carpet_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
[...]
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `carpet_category_info` (
`id` int(11) NOT NULL,
`price-per-sqf` int(11) NOT NULL,
`name` varchar(50),
[...]
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
then all your joins become simple, and fast.. And accurate.

one to many relation-displays first row only

after going through many attempts, i finally can display data from child table. I have 2 tables, user (parent) and useradvert(child).
user
-id (pk)
-name
-username
-telno
useradvert
-id(index)
etc.........
it's a 1 to many relation. from table users to table useradvert. table users suppose to pull many rows from table useradvert based on specific id which matches id in table users. But, instead it only display first row from useradvert. No matter how you login with different username, you will always see the first row from useradvert and not the rows that is supposed to display. For ur info, I'm a newbie. Any help is appreciated. tqs.
below is extract;
$query = "SELECT * FROM users,useradvert WHERE users.id=useradvert.id";
$stmt = $conn->prepare($query);
$stmt->execute();
$res = $stmt->get_result();
$row2 = $res->fetch_array();
$_SESSION['name2'] = $row2['name2'];
$_SESSION['color2'] = $row2['color2'];
$_SESSION['hobby2'] = $row2['hobby2'];
$_SESSION['radiobtn'] = $row2['radiobtn'];
$_SESSION['kupon'] = $row2['kupon'];
$_SESSION['image'] = $row2['image'];
$_SESSION['image2'] = $row2['image2'];
below is extract -continue on same page
<?php
//display record from table- useradveret -(child table)
// while($row = $res->fetch_array()){
echo $_SESSION['name2']."<br/>";
echo $_SESSION['color2']."<br/>";
echo $_SESSION['hobby2']."<br/>";
echo $_SESSION['radiobtn']."<br/>";
echo $_SESSION['kupon']."<br/>";
echo $_SESSION['image']."<br/>";
echo $_SESSION['image2']."<br/>";
// }
?>
table query for useradvert
-- Table structure for table useradvert
CREATE TABLE IF NOT EXISTS `useradvert` (
`id` int(10) unsigned NOT NULL,
`name2` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`color2` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`hobby2` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`radiobtn` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`kupon` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`image` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`image2` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `useradvert`
--
INSERT INTO `useradvert` (`id`, `name2`, `color2`, `hobby2`, `radiobtn`, `kupon`, `image`, `image2`) VALUES
(97, 'testthree nickname', 'colorthree', 'hobbythree', 'female', '', 'uploads/testpic1.jpg', 'uploads/testpic2.jpg'),
(99, 'testfivenamecick', 'testfivehcolor', 'testfivecolor', 'female', '', 'uploads/testpic3.jpg', 'uploads/testpic4.jpg'),
(97, 'lagitestthree', 'trheecolor', 'threehobby', 'female', '', 'uploads/testpic5.jpg', 'uploads/testpic6.jpg');
--
-- Constraints for dumped tables
--
--
-- Constraints for table `useradvert`
--
ALTER TABLE `useradvert`
ADD CONSTRAINT `useradvert_ibfk_1` FOREIGN KEY (`id`) REFERENCES `users` (`id`);
I guess your sql query is not correct. Yo use the id field of useradvert table, but that is the index field of that table. That looks wrong. You should have a foreign key userId in useradvert table for the join. Then you query should look something like this:
SELECT * FROM users u
INNER JOIN useradvert ua ON u.id = ua.userId
Then you should get all useradvert fields for the user.
The 2 tables should look something like this:
Table user:
id | name | ...
1 | Ben | ...
2 | Markus | ...
Table useradvert:
id | userid | ...
1 | 1 | ...
2 | 1 | ...
userid in useradvert is the foreign key to create the relationship between the 2 tables. Does that make sense?

how to select from database based on a match in category?

Is it possible to select certain rows based on a category which matches it when there are multiple categories in the entry? It's hard to explain so I'll show you. The row I have in the database looks like this:
**article_title** | **article_content** | **category**
Article-1 | some content here | one,two,three,four
So my query looks like this:
$sql = mysqli_query($mysqli_connect, "SELECT * FROM table WHERE category='
preg_match(for example the word three)'");
Reason why I'm doing that is some articles will be available on multiple pages like page one and page three...so is there a way to match what I'm looking for through the entry in the database row?
You should use a more flexible database design. Create a separate table that holds the one-to-many relationships between (one) article and (many) categories:
CREATE TABLE IF NOT EXISTS `articles` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`article_name` varchar(255) NOT NULL,
PRIMARY KEY (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
INSERT INTO `articles` (`article_id`, `article_name`) VALUES
(1, 'Research Normalized Database Design');
CREATE TABLE IF NOT EXISTS `article_category` (
`article_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `article_category` (`article_id`, `category_id`) VALUES
(1, 1),
(1, 2);
CREATE TABLE IF NOT EXISTS `categories` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`category_name` varchar(255) NOT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `categories` (`category_id`, `category_name`) VALUES
(1, 'Databases'),
(2, 'Normalization');
Querying then becomes as simple as:
SELECT
*
FROM
articles AS a
JOIN
article_category AS pivot ON a.article_id = pivot.article_id
WHERE
pivot.category_id = 2
Or do something like:
SELECT
*
FROM
articles AS a
JOIN
article_category AS pivot ON a.article_id = pivot.article_id
JOIN
categories AS c ON pivot.category_id = c.category_id
WHERE
c.category_name = 'Normalization'

Display category name from a table

i have two tables in my database. One name jokes and the other named category.
jokes
CREATE TABLE `jokes` (
`joke_id` int(11) NOT NULL AUTO_INCREMENT,
`joke` varchar(1024) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`joke_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
category
CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(51) NOT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
and i was wondering what the query would be to find the category name of a joke so it can be displayed on the home page like title:"Celebrity Joke" joke:"Miley Cyrus is a joke" and so on..
Would anybody be able to help me out on this problem, im guessing it will be a query/string assigned to a variable named $category_name which will reference both tables, but again, im not too sure how to go about it.
Try this first joining two tables:
SELECT
* //You can filter more your columns here
FROM
jokes
LEFT JOIN category ON
jokes.category_id = category.category_id
Now after this statement you can add a WHERE CLAUSE and it could be something like this
WHERE category.category_name like '%Miley%'
Means you will retrieve records having a category that has name of Miley
If you were going to do this with all jokes/categories it would look like:
SELECT * FROM jokes UNION SELECT * FROM category
However if you wanted to do a single joke you could just use the answer posted by Drixson. IF you wanted all the jokes from one category you would do:
SELECT * FROM jokes WHERE category_id=CATEGORY_ID
Some PHP you could use to display jokes from each category:
//Cat ID, using 1 for example
$category = 1
//Query
$query = "SELECT * FROM jokes WHERE category_ID=:cat";
//Establish PDO, prepare, apply parameter, execute, fetch data
$search = new PDO("mysql:host=HOST;dbname=DB",USERNAME, PASSWORD);
$runQuery = $search->prepare($query);
$search->bindParam(':cat', $category, PDO::PARAM_INT);
$search->execute();
$results = $search->fetchAll();
//For every row display joke_id and the joke
foreach($results as $joke){
echo $jokes["joke_id"] . " - " . $jokes["joke"];
}
//Kill
$results = null;
Hope it helps. PDO is pretty easy to pick up so if you need anymore help just search for a PDO tutorial on Google.

Categories