Display category name from a table - php

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.

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.

Correct mysql query to query one table and have that provide information for another table query

I have 2 separate tables, both of which I need to query simultaneously to get the correct information to display. The tables are members and posts. Through an html form, a user enters criteria for the members table, and then I need to use the primary index of all those specific members to find all the posts submitted by those members and then do a sort on the posts table results. The results will be a mixture of rows from the two tables. Both tables have a primary index of the name 'id'. So far what I've come up with is:
$sql_get_posts = mysqli_query($link, "(SELECT id, username FROM members WHERE active='y' AND gender='M' AND city='Yuma' AND state='Arizona') UNION (SELECT * FROM posts WHERE member_id='id' AND active='y' ORDER BY list_weight DESC)") or die(mysqli_error($link));
The error I'm getting is "The used SELECT statements have a different number of columns".
I need to then cycle through the returned results from both tables to populate the content seen by the user:
<?php
while ($row = mysqli_fetch_array($sql_get_posts)) {
$post_id = $row['id']; //This should be the post primary index named 'id', not the member primary index also name 'id'
$member_id = $row['member_id']; //This is the member_id row in the post table referencing this particular member who wrote this post
$member_username = $row['username']; //This is a row stored in the member table
$title = $row['title']; //This is a row stored in post table
******//and on and on getting rows from only the post table
}
Edit My SQL tables:
CREATE TABLE IF NOT EXISTS `members` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`age` varchar(3) NOT NULL,
`gender` varchar(1) NOT NULL,
`city` varchar(20) NOT NULL,
`state` varchar(50) NOT NULL,
`active` enum('y','n') NOT NULL DEFAULT 'y',
`created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL,
`title` text NOT NULL,
`comments` enum('y','n') NOT NULL DEFAULT 'y',
`post_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`list_weight` double NOT NULL,
`active` enum('y','n') NOT NULL DEFAULT 'y',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=47 ;
Use join instead of union, union assumes the tables you're combining are similar, whereas join merges the columns of two tables.
Something like:
SELECT members.id, members.username, posts.*
FROM members
INNER JOIN posts
ON members.id = posts.member_id
WHERE members.active='y' AND members.gender='M' AND members.city='Yuma' AND members.state='Arizona'
ORDER BY posts.list_weight DESC
SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types. Also, the columns in each SELECT statement must be in the same order.
But you have selected only 2 columns in first query and "*" for second select query
use joins
SELECT m.id, m.username,p.* FROM members m JOIN posts p on m.active='y' AND m.gender='M' AND m.city='Yuma' AND m.state='Arizona' and p.member_id='id' AND p.active='y' ORDER BY p.list_weight DESC
or you can use
SELECT m.id, m.username,p.* FROM members m,posts p where m.active='y' AND m.gender='M' AND m.city='Yuma' AND m.state='Arizona' and p.member_id='id' AND p.active='y' ORDER BY p.list_weight DESC

Uploading data into two mysql tables

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);

How to display multiple categories and products underneath each category?

Generally there is a category menu and each menu links to a category page where shows all the items under that category.
Now I need to show all the categories and items underneath with PHP/MySQL in the same page.
So it will be like this.
Category 1
description of category 1
item 1 (some details, such as name, thumbnail etc for each item)
item 2
..
Category 2
description of category 2
item 5
item 6
..
Category 3
description of category 3
item 8
item 9
...
...
I have category and product table in my database.
It seems like I have to loop through categories and under each category I have loop through to get all the items.
But I am not sure how to proceed.
CREATE TABLE IF NOT EXISTS `omc_product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`shortdesc` varchar(255) NOT NULL,
`longdesc` text NOT NULL,
`thumbnail` varchar(255) NOT NULL,
`image` varchar(255) NOT NULL,
`product_order` int(11) DEFAULT NULL,
`class` varchar(255) DEFAULT NULL,
`grouping` varchar(16) DEFAULT NULL,
`status` enum('active','inactive') NOT NULL,
`category_id` int(11) NOT NULL,
`featured` enum('none','front','webshop') NOT NULL,
`other_feature` enum('none','most sold','new product') NOT NULL,
`price` float(7,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
CREATE TABLE IF NOT EXISTS `omc_category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`shortdesc` varchar(255) NOT NULL,
`longdesc` text NOT NULL,
`status` enum('active','inactive') NOT NULL,
`parentid` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
The simple way: do one query to fetch the categories, and then a separate query to fetch each list of products. Something like:
<?php
// Shortcuts to essential string-escaping functions
//
function h($s) {
echo htmlspecialchars($s, ENT_QUOTES);
}
function u($s) {
echo urlencode($s);
}
function m($s) {
return "'".mysql_real_escape_string($s)."'";
}
// Get all categories
//
$q= mysql_query('SELECT id, name, shortdesc FROM omc_category WHERE status='active' ORDER BY id');
$categories= array();
while ($categories[]= mysql_fetch_assoc($q)) {}
?>
<?php foreach ($categories as $category) { ?>
<h2><?php h($category['name']); ?></h2>
<p><?php h($category['shortdesc']); ?></p>
<?php
// Get all products for a category
//
$q= mysql_query('SELECT id, name FROM omc_product WHERE status='active' AND category_id='.m($category['id']));
?>
<ul>
<?php while ($product= mysql_fetch_assoc($q)) { ?>
<li>
<a href="/product.php?id=<?php u($product['id']); ?>">
<?php h($product['name']); ?>
</a>
</li>
<?php } ?>
</ul>
<?php } ?>
(Note: the m() call here is not strictly necessary because integers are safe to insert into an SQL query without escaping. But it's not a good idea to get into that habit, as if you did it with strings you'd have an SQL-injection security hole. I'm using the mysql_ interface with manual escaping here; you're usually much better off with parameterised queries using mysqli_ or PDO, where available. This prevents you from having to worry about SQL escaping. The same goes for u()'s URL-encoding: not necessary for integers, but generally worth getting into the habit of using.)
For a simple site, this would be OK. For a larger site with many categories you might want to get all your products in a single query, which you could do like:
SELECT omc_product.id, omc_product.name, omc_product.category_id
FROM omc_product
JOIN omc_category ON omc_category.id=omc_product.category_id
WHERE omc_product.status='active' AND omc_category.status='active'
ORDER BY category_id, id
and then on each row you get back, check to see if the category_id has changed since the previous row. If it has, output the name and shortdesc of the corresponding category object from the previous query. (Or you can select omc_category.name and shortdesc in the above query too to get them at the same time, though you might not want to do that if the descriptions can be quite long.)
Also, consider using an InnoDB table with proper FOREIGN KEY references between your tables. There's little good reason to be using MyISAM today (except for FULLTEXT).
`parentid` int(11) NOT NULL,
Oh, I hope that doesn't mean you've got hierarchical categories! That would make everything more complicated. See also: nested sets.
It seems like I have to loop through
categories and under each category I
have loop through to get all the
items.
you query to get all your categories
you loop your categories • you display the category general header • you query to get all the items of that category
you loop through the items and display them
SELECT A.`id` AS catid, A.`name` AS catname, ..., B.`id` AS prodid, ...
FROM `omc_category` A LEFT JOIN `omc_product` B ON (B.`category_id` = A.`id`)
ORDER BY A.`id`
You dind't even need to order by category, but it makes processing the result easier.
NOTE: if the result set is very large, I would favor Lo'oris's approach.

Categories