-1

I have a PHP script to save new articles into MySQL with the following parameters:

ID, Date, Category, Title, Content, Slug Where the Slug is the same title but with - dashes like this:

this-is-a-nice-title

Then I have the articles.php where all articles are displayed and linked to read-article.php where the selected article can be read in a seo-friendly url like this

domain.com/news/this-is-a-nice-title

Just like anyone else does, the page read-article.php sends a query to MySQL like this:

SELECT * FROM articles WHERE slug=?

until that everything is fine, every tutorial on Internet tells you to do that and it works.

But here is the problem: If some articles have the same title by any reason, any error or misstake, that would be a problem. So it is best to query using the ID instead like this:

SELECT * FROM articles WHERE id=?

The thing is that I cannot make it to work, I just get error 404 all the time because when there are no results I set it to go to error-404.php while testing/developing

No tutorial teach you how to create friendly urls without querying MySQL by the slug name. Thus my question is: Is it possible to do it another way, tother than to query the slug in MySQL?

  • 2
    **Warning:** Your code is vulnerable to SQL Injection attacks. You should use parameterised queries and prepared statements to help prevent attackers from compromising your database by using malicious input values. http://bobby-tables.com gives an explanation of the risks, as well as some examples of how to write your queries safely using PHP / mysqli. **Never** insert unparameterised data directly into your SQL. The way your code is written now, someone could easily steal, incorrectly change, or even delete your data. – ADyson Jun 07 '23 at 12:04
  • https://phpdelusions.net/mysqli also contains good examples of writing safe SQL using mysqli. See also the [mysqli documentation](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) and this: [How can I prevent SQL injection in PHP?](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) . Parameterising your queries will also greatly reduce the risk of accidental syntax errors as a result of un-escaped or incorrectly quoted input values. If you learnt your current technique from a tutorial or book, please don't use that resource again. – ADyson Jun 07 '23 at 12:04
  • 2
    "_every tutorial on Internet tells you to do that_" I don't think so - you're reading the wrong tutorials. As ADyson mentioned this makes your site highly vulnerable. – brombeer Jun 07 '23 at 12:05
  • 3
    If articles can have the same title/slug you could use the id or a date (something unique) in your url to identify the article: `/news/12/this-is-a-nice-title` or `/news/20230607/this-is-a-nice-title` – brombeer Jun 07 '23 at 12:09
  • 2
    If the question is not about SQL injection then you should not have shown SQL injection vulnerable code. Please do not share bad practices online. – Dharman Jun 07 '23 at 12:13
  • 1
    `NOTE: This is not a post about SQL injections neither vulnerabilites`...perhaps, but that's why the issue is mentioned in a Comment rather than an Answer. It's still something you need to pay urgent attention to though. And if it's not representative of your real code, then it doesn't belong here either. We expect people to post a [mre] of their issue, as per the guidance in [ask]. Thanks. – ADyson Jun 07 '23 at 12:13
  • ok I fixed it, the question remains about the possibility to do another way than by slug-name –  Jun 07 '23 at 12:23
  • 1
    _"If some articles have the same title by any reason"_ ... then your system should realize that the moment the second one gets created. The user has input the title, based on which you create the slug `this-is-a-nice-title`- and now you go check in your database first, whether an article with that slug already exists. And if so, give the new one a _different_ slug - for example by appending a "counter" to the new one, `this-is-a-nice-title-2` (Of course you would also have to check that `this-is-a-nice-title-2` does not _already_ exist at that point.) – CBroe Jun 07 '23 at 12:26
  • 1
    "_So it is best to query using the ID instead_" Where would you get the ID from in an URL like `/news/this-is-a-nice-title`? – brombeer Jun 07 '23 at 12:27

2 Answers2

0

This sounds like it's likely to be an X-Y Problem.

If articles can have the same title, then your system needs to make sure they aren't saved with the same slug.

For example, if it finds that it's trying to save a value which is a duplicate of an existing one, then it could append some random character, or a sequence number, a timestamp - anything like that which makes it unique, on the end of the slug.

It probably doesn't really matter exactly how you do it, the point is to have a process which ensures there can't be duplicates. It's generally easier to stop the problem at the source, rather than trying to find workarounds for it.

Ultimately if there are two identical slugs, the system will never be able to tell them apart when parsing the URL, so you can't allow that to occur in the first place.

There is no question of querying by the ID, because you don't have the ID at the time you would need it. All you have is the slug value from the URL. That is what shows which post the user has requested to display, and there URL doesn't contain any other information about that. Therefore, that's the thing you need to query by, and so to make that work, your system must ensure that each slug is unique in your database.

ADyson
  • 57,178
  • 14
  • 51
  • 63
  • so there is not another way other than to query the slug ? –  Jun 07 '23 at 12:24
  • I think you have to query the slug, because that's the only information you get from the URL to show which post should be displayed. That is the piece of data which links the URL to the post. Therefore you must query using it, and that in turn means it must be unique. – ADyson Jun 07 '23 at 12:26
0

YES it is possible do achieve in a very easy way:

When you link your visitors using the slug, you simply add the id to it, for example:

<a href="<?php echo $row['slug'];?>&id=<?php echo $row['id'];?>">
<?php echo $row['title'];?>
</a>

And then in the slug page you just query select by ID instead of slug Don't forget to edit your htaccess file like this:

RewriteRule ^([-/.a-zA-Z0-9]+)$ slug.php?slug=$1&id=$2 [QSA,END]
Kamikaza
  • 1
  • 1
  • 18