count the number of comments (php/mysql) - php

i am using this code so i can count the number of comments for each article
SELECT *, COUNT(comment_id) as count
FROM article_comments
WHERE article_id =colname
GROUP BY article_id
this is what my comment table look like
http://i54.tinypic.com/2cdu3dk.png
i want to save these number in another table (the articles table.. each number next to it's article ) like this
http://i54.tinypic.com/2dgm82u.png
and when the user enter a comment..the number change automatically
someone help me with the code
or if there is another way to do this
i know it's a long question
but i have been trying to solve this for like..forever
thanx

You could set a TRIGGER that updates the comment count table every time a comment is added. Or you could simply add the UPDATE query right after the INSERT query in your comment page.

You probably do not need a lookup table. 1 article has many comments. Therefore, structure your comments table something like this (add an article field);
id | article | content
-------------------------
1 | 1 | Comment 1 for article 1.
2 | 1 | Comment 2 for article 1.
3 | 2 | Comment 3 for article 2.
When displaying your article, list comments using the following query;
SELECT a.id, a.content FROM articles a WHERE a.article = :myArticleId
When creating a new comment:
INSERT INTO comments (article, content) VALUES (:currentArticleId, :content)
UPDATE article SET commentCount = commentCount + 1 WHERE article = :currentArticleId
The articles table will look something like this;
id | commentCount | content
------------------------------
1 | 0 | Article with 0 comments.
2 | 3 | Article with 3 comments.
This requires some work on your part, but it has more benefits than drawbacks.
Your proposed solution has 2 large drawbacks;
COUNT() in SQL does not scale very well and can be slow, normally it can be avoided.
The lookup table adds unnecessary complexity to your application.
Triggers should also always be avoided. They create "magic" conditions - your database can be changed without you knowing about it. Triggers are often more difficult to change than code too.

$query = mysql_query("SELECT * FROM article_comments WHERE article_id =".$youarticleId);
//the number of comments is :
$number_Of_Comments = mysql_num_rows($query);
//save it to another table
$query2 = mysql_query("UPDATE yourTable set numberOfComments =".$number_Of_Comments);

on saving comments, try to:
update table_where_you_count_the_comments set number_of_comments = number_of_comments +1 where article_id = theID limit 1;
or look for mysql triggers.

you're asking the sql server to select everything and the count id at the same time, use one of them and give it a where close, and Bingo!

Related

Creating a related articles query in PHP

I'm trying to make something similar to "related articles". This is what I have.
$query = "SELECT * FROM posts WHERE post_tags LIKE '%$post_tags%'";
I want it to 'select all from post where the post tags are similar to the current post's tags'.
Note: The tags look like this in the database: "tech, news, technology, iphone"
I looked into things like
$tags = explode(",", $post_tags );
But I'm not sure.
Use FullText search -- docs
SELECT * FROM `posts` WHERE MATCH(post_tags) AGAINST('$post_tags' IN BOOLEAN MODE)
Live demo
The query will require you to add a FULLTEXT index to your post_tags table column (unless you have the older MyISAM table). This query will be a lot faster than your current attempt.
query to add the index
ALTER TABLE `posts` ADD FULLTEXT INDEX `tag_search` (`post_tags`)
A better, faster approach
Change how you store the post-to-tag relationship in the DB. Your posts table should not be used to store tags because one post has many tags, but each post has only one record in the posts table. Instead, have a two other tables:
tags table
tag_id | name
1 | technology
2 | news
3 | hobbies
post_tags table
post_id | tag_id
1 | 1
1 | 3
2 | 1
Notice it's easy to tell that post_id #1 has the technology and hobbies tags. This will make your queries easier, and faster.
Even faster!
If you do want to store everything in the posts table but have even faster performance, you will need to store your tags as bit flags. For instance, if the following is true in your PHP application:
$techBit = 0b001; // number 1 in binary form
$newsBit = 0b010; // number 2 in binary form
$hobbiesBit = 0b100; // number 4 in binary form
Then it's easy to store tags in one field. A post that has technology and hobbies tag would have a value:
$tag = $techBit | $hobbiesBit; // 1 + 4 = 5
And if you wanted to search for all records with technology or hobbies, you would do:
// means: records where post_tags has either techBit or hobbiesBit turned ON
SELECT * FROM `posts` WHERE (`post_tags` & ($techBit | $hobbiesBit)) > 0
Well instead of "LIKE" you could use the "IN" clause.
$Results = join("','",$post_tags);
$SQLQuery = "SELECT * FROM galleries WHERE id IN ('$Results')";
Example: Passing an array to a query using a WHERE clause

Giving several unique ID´s to a MySql row and using php to show all rows with one special ID

I am trying to make a system that manages a lot of articles and some articles are needed in more than one article series.
I am wondering how I can give one row in Mysql several unique ID´s and extracting them from the database with PHP.
It only reads the first ID and not the next.
I have tried seperating them with a comma, but if I write 10, 122.
Only 10 will be read as an ID and 122 will be ignored.
I am not very skilled with programming, but I am doing my best to learn it, Hope you can help me! :-)
The code I use to sort the articles in the system.
$id=$_REQUEST['id'];
$ro=mysql_query("SELECT * FROM blog_articles
WHERE fk_semikatagori_id=".$id."
ORDER BY ABS(sortering) ASC") or die(mysql_error());
Each article is unique, right? Keep it having a unique ID. What you should do is create an additional table, like #user574632 has suggested, where you don't have any unique fields but this will allow you to create your "categories" (or "series") and add each unique article to that table. You then search THAT table to obtain all the IDs of articles that are supposed to be in a series.
E.g.
Articles
========
ID | Title | Body
1 | My Article | This is my article
2 | StackExchange | My article on Stack Exchange...
Categories
========
SeriesID | ArticleID
1 | 1
1 | 2
2 | 1
You then query the categories table to obtain all the article IDs you require for your series...
If you can't fix the table design, use FIND_IN_SET:
$ro=mysql_query("SELECT * FROM blog_articles
WHERE FIND_IN_SET($id, fk_semikatagori_id)
ORDER BY ABS(sortering) ASC") or die(mysql_error());

Best Way To Track Page Views and store in MySQL

I am currently developing an article driven site and would like to know the best way to track page hits so I can display something along the lines of "Most Viewed" or "Most Popular Articles". I display my articles through a $_GET on a single PHP page (e.g article.php?id=2). I read somewhere that an INSERT INTO was the way to go and I tried to do:
$page_views = $conn->query("INSERT INTO blog_posts (views) VALUES (views = views+1");
Alas, this did not work.
In summary I want to be able to:
Add 1 to the number of page views on an specific id for each time someone lands on the page (e.g articles.php?id=3) not just articles.php
Thanks in advance.
(Sorry if I haven't made this clear enough. If you want anything clarifying just ask.)
Do you intend to keep a separate table for the counts? If so,
|page_views |
|blog_id|count|
+-------+-----+
| 1 | 12 |
| 2 | 33 |
with blog_id being a primay key with unique enforced
you could use on duplicate key to create a row if it doesn't exist and update the count if it does
("INSERT INTO page_views (blog_id,count) VALUES ($blog_id,1) ON DUPLICATE KEY UPDATE count = count + 1")
Why don't you try with update statement:
"UPDATE blog_posts SET views = views+1 WHERE id = $id"
Your insert statement will add a new row in the database, what probably is not what you want.
Use an update query to increment the counter.
UPDATE blog_posts SET views = views+1 WHERE id = 'SOME NUMBER'
Where your each row in the blog_posts table has a numberic views field and an id.
SQL Fiddle:
http://sqlfiddle.com/#!2/0915b/1

Check if an id exists in a table before adding it to another table

I'm doing a small thing like the like feature you see on facebook. So the way I'm doing it is like this. I have a table called products which contains products that people can like.
Like this (stripped down):
id | prodName | status (0=clear, 1=blocked)
----------------------------------------------------------
1 | Philips Food Processor | 0
2 | Le Sharp Knife | 0
3 | Ye Cool Fridge | 0
Then comes the `likes` table like this:
id | prodName | prodId | userId
--------------------------------------------
1 | Philips Food Processor | 1 | 1
2 | Le Sharp Knife | 2 | 1
3 | Ye Cool Fridge | 3 | 1
4 | Ye Cool Fridge | 3 | 2
I need to check, before adding to the likes table, if a product with that id actually actually exists in the products table and its status = 0. I currently do this with a lot of php code. What would be a good way to do this using sql? Is it possible? Using foreign keys or something like that?
I'm using innodb table type.
You can do a conditional insert. For product 6 and user 7:
insert into Likes
(prodName, prodId, userId)
select prodName
, id
, 7
from Products
where id = 6
and status = 0
If this inserts no rows, you know that the product did not exist with status 0.
If you just want to phrase the insert so it follows the rules, then you can use insert . . . select as follows:
insert into likes(prodId, userId)
select <prodid>, <userid>
from products p
where p.prodid = <prodid> and status = 0
I don't think MySQL supports "partial" foreign key constraints, where you can also include the requirement on the flag.
And, you shouldn't put the product name int he likes table. You should look it up in the products table.
The key element of trying to add something to the likes table that does not exist in the product table is the feedback to the user that lets them know they're doing it wrong. Any answer you determine on should not ignore the user feedback side of things - which is basically going to require your PHP code.
However, yes - there is a way to do it via foreign keys. You can index the prodid in the second table, and reference it as a foreign key to the first table.id. This means that if you try an insert and you get an error, there's a chance that the problem is that you're trying to add something without a match in the first table.
However, trying to determine precisely what the error is so you can determine the proper logic to respond to that error causes its own mass of php code, and is less easily transparent for future developers to maintain. I'd suggest a simple method in your Product object: isValid( id ) that returns true/false - so your 'check for this' code simply goes if( Product.isValid( prodId ) ){ Like.insert( userId, prodId ); }
But at the same time, I'd REALLY recommend a foreign key constraint along with the php code you're probably already using, just as insurance against your database becoming cluttered with unlinked rows. It's usually best to have multiple barriers against bad data.
Additionally ... is there a reason why you're storing the product names both in the product table AND in the likes table? I don't see why you'd need it in the likes table.
--Check to see if cleared product exist in products table
Select count(*) from products p where p.status = 0 and p.id = %IDVALUE
--Check if your user previous liked product
Select count(*) from products p, likes l where p.id = l.prodId and l.userId = %USERID
In your code you can execute the statements (replace %IDVALUE and %USERID with actual values) and check the return column to get the count and preform your custom logic.
Currently you require the prodId to populate the likes table, hence you need to lookup the data regardless of the contraint regarding blocked. Hence:
INSERT INTO likes (prodname, prodId, userId)
SELECT prodname, id, 123456
FROM products
WHERE prodname='Le Sharp Knife'
AND status=0;
(just substitute 123456 and 'Le Sharp Knife' for the parameters you need).
Yuo need to query database to check record,
for example you product id is 2 so your query would be something like
$query = select * from 'your-like-table' where 'prodId ' = 'ID';
then
if ( !mysql_query('your-db',$query)):
if you come under this condition then it's the time when you enter your like to database
endif;
hope it helps

Rating System in PHP and MySQL

If we look at the stackoverflow website we have votes. But the question is what is the bestway to store who has voted and who has not. Lets also simplify this even more and say that we can only vote Up, and we can only Remove the Up vote.
I was thinking having the table to be in such form
question - Id(INT) | userId(INT) | title(TEXT) | vote(INT) | ratedBy(TEXT)
Thre rest is self explanitory but ratedBy is a Comma Seperated Id values of the Users.
I was thinking to read the ratedBy and compare it with the userId of the current logged in User. If he dosent exist in the ratedBy he can vote Up, otherwise he can remove his vote. Which in turn will remove the value from ratedBy
I think to make another table "vote" is better. The relationship between users and votes is n to n, therefore a new table should be created. It should be something like this:
question id (int) | user id (int) | permanent (bool) | timestamp (datetime)
Permanent field can be used to make votes stay after a given time, as SO does.
Other fields may be added according to desired features.
As each row will take at least 16B, you can have up to 250M rows in the table before the table uses 4GB (fat32 limit if there is one archive per table, which is the case for MyISAM and InnoDB).
Also, as Matthew Scharley points out in a comment, don't load all votes at once into memory (as fetching all the table in a resultset). You can always use LIMIT clause to narrow your query results.
A new table:
Article ID | User ID | Rating
Where Article ID and User ID make up the composite key, and rating would be 1, indicating upvote, -1 for a downvote and 0 for a removed vote (or just remove the row).
I believe your design won't be able to scale for large numbers of voters.
The typical thing to do is to create to tables
Table 1: question - Id(INT) | userId(INT) | title(TEXT)
Table 2: question - ID(INT) | vote(INT) | ratedBy(TEXT)
Then you can count the votes with a query like this:
SELECT t1.question_Id, t1.userId, t1.title, t2.sum(vote)
FROM table1 t1
LEFT JOIN table2 t2 ON t1.question_id = t2.question_id

Categories