#1
Hi,

I have so far only used primary key ids everywhere, and this could be a security/privacy concern I'm now learning.

- How do you use primary keys and/or uuid?
- uuid as primary key?
- uuid in frontend/links and id backend/sqls?
- Is there any Trongate related functions, functionality for this?
- Best practice to set a uuid in mysql? (up-to-date version, performance etc.)

Grateful for any tips.
#2
I'm not aware of any specific support/best practices from Trongate or other PHP tools about this.

The most relevant thing I've seen is this video: https://www.youtube.com/watch?v=lopIg_f90MI

He obfuscates the raw table IDs in the output HTML by printing their MD5 hash.

The frontend part is discussed around 13:30 and the backend SQL around 23:30.

The way I'd do it in Trongate would be something like:

In my view:



You'll notice I'm using Trongate MX; that's not related to your question, just the example I had handy.

In my controller:

#3
In general the assumption in Trongate seems to be integer IDs, some methods on Db class assumes int $id but there’s nothing stopping you from using a string ID via query and query_bind method.

- How do you use primary keys and/or uuid?
Refer to MariaDB docs or use like Ramsey/uuid in php
- uuid as primary key?
Sure, call Db::query_bind($sql) or Db::query($sql) directly
- uuid in frontend/links and id backend/sqls?
Doable, I also had a quick glance over Pagination class - it’s easily configured and the actual querying is left to the consuming module. Read Trongate_administrators for sample code.
- Is there any Trongate related functions, functionality for this?
No, not from what I found source diving a bit.
a good contribution may be a uuid helper module.
- Best practice to set a uuid in mysql? (up-to-date version, performance etc.)
Generally I find the most success using recent MariaDB, I’m generally running version 12.3 for my development and servers.
#4
Just look at the URL of this page. Right now. Look at your browser bar.



That's make_rand_str(32). But here's what the frameworks crowd doesn't understand. We didn't just grab A-Z, a-z, 0-9 like amateurs. We removed the confusing characters. No zeros. No ones. No lowercase L, no uppercase O, no lowercase O, no uppercase I. Why? Because O and 0 look the same. 1 and l look the same. i and j get squinted at. We made it human-friendly.

So what's left? 24 uppercase letters, 24 lowercase letters, 8 numbers. Total: 56 possible characters per position.

Now do the maths. 56 to the 32nd power. That is approximately 1.3 × 10⁵⁶ possibilities.

Let me put that number in your hand. The number of atoms on planet Earth is about 1.33 × 10⁵⁰. You are more likely to pick one specific atom out of the entire planet, blindfolded, one try, than you are to guess this URL.

And a collision? Two different database records getting the same random string? You would need to generate somewhere around 10²⁸ records before probability even reaches 1%. That is ten million billion billion records. You are not building that. Neither is Google. Neither is anyone.

But here is what I really need you to hear.

That random string in the URL is not a security measure. Let me say it again. Security by obscurity is the work of an amateur. If you are hiding an ID in a URL and calling it secure, you have already lost. That is not PHP. That is not Trongate. That is just wishful thinking.

Using a random string in the URL for security is like hiding your house key under the mat and calling it a lock. The mat is fine for convenience. It stops nobody. You still need the lock.

The random string in your URL? That is the mat. It stops casual curious fingers from changing ?id=1 to ?id=2. That is all it does. It is convenient. It is not security.

Real security, the kind that actually protects your data, happens elsewhere. Trongate has a complete token-based authentication and authorisation system for that. You want to protect a record? Use trongate_tokens. Use the trongate_security module. It's all there! That is the lock.

So if you are sitting there thinking, 'I will just MD5 my integer IDs and that is secure,' stop. You are building on sand. The frameworks world wants you to believe you need UUIDs, service containers and autoloader symphonies just to hide an ID. That is the illusion of complexity. They will sell you a 10,000-line UUID library to solve a problem that a 12-line function handles with better readability and zero dependencies.

Do not confuse unguessable with unauthorised.

Here is the reality. make_rand_str(32) gives you an unguessable string. Store it. Query it. Done. That is the mat. Then layer real authentication and authorisation on top. That is the lock.

That is not a compromise. That is Native PHP.
#5
Hi all,

DC pretty much nailed the spirit of this 👍

There’s a tendency in the wider PHP ecosystem to over-engineer simple problems, and this is a good example. The goal here is not “perfect identifiers” - it’s practical, safe, and maintainable apps.

DC’s point about make_rand_str(32) is spot on:

Simple
Readable
No dependencies
Effectively unguessable
Cleaner than UUIDs in URLs

That aligns very well with the Trongate philosophy: keep things lean, native, and under your control.

That said, I also want to acknowledge the other replies, as they provide useful context.

@sasin91 is absolutely right:

Trongate doesn’t force you into INT IDs
You can use strings / UUIDs via query() / query_bind()
A UUID helper module could be a nice contribution

So yes - you can go full UUID if your project genuinely needs it.

@ak1’s MD5 approach works as a quick obfuscation layer, but it’s worth being clear:

It’s deterministic
It can be brute-forced
It doesn’t really solve the underlying problem

So it’s fine as a lightweight mask, but not something to rely on for security.

Where this all lands (practical Trongate approach):

Keep it simple and split responsibilities:

Use INT id as your primary key (fast, efficient)
Use a random string for public exposure

Example:



Generate it with:



Use it in URLs, query by it in controllers, done.

Important note (this matters more than IDs):

Even with UUIDs, hashes, or random strings:

You MUST still check permissions
You MUST still validate access

Identifiers are not security — they’re just identifiers.

Bottom line

Don’t overcomplicate it
Don’t fight the framework
Don’t import a 10k-line UUID library for a 12-line problem

Trongate gives you what you need out of the box.

Use it, keep it clean, and move on to building something that matters.

Cheers.

PS. Bring back Grady - he/she/ it would have nailed this thread too (AI fan club)
#6
Hi Dafa,

I feel a bit like I've intervened with a robbery while, the whole time, Spider Man was perched on the rooftop - looking over.

What I mean by that is, I don't think I'm as good at answering those kinds of questions and you, and some of the others in our midst.

Now, maybe the person who asked the question won't even show up again. Hopefully they will, but if not then that's fine and we wish them well.

However, personally speaking, I'd rather leave questions like the above to other people. I will, however, offer one word of advice. When you're addressing questions like the above, please be assertive. Not rude. Not unpleasant. Not uncool. Just assertive.

With a thread this like, it's very easy to go down a rabbit hole and before long, we're apologising for make_rand_str() and we've got a whole bunch of people speculating about a security hole that doesn't exist. Now, I used AI to get the numbers for my probability calculations (above). Of course I did! I also use AI for proof reading sometimes. There's nothing wrong with that. However, the actual argument and the tonality - you'll never get it from AI. All you'll get is some wishy washy baloney.

So, let us be friendly. Let's us be welcoming of all. And yes... I'll even say that ghastly word that, for all the wrong reasons, has become political - let us be inclusive.

But let's also be confident. Native PHP beats over-engineering and third-party dependency every time. I don't need to tell Dafa this because he's already a confident and assertive person. I suppose I'm trying to give a friendly reminder to any of the regulars out there. It's okay to be assertive.

Right now this forum is relatively quiet. I promise, it won't be quiet for much longer.

Best of luck!

DC

PS - I'll bring Grady back if the forums end up being overwhelmed. Grady cannot answer questions the way you do. So, I think we're good. I have Grady working on the reference guide today. Hopefully it'll work.
#7
Thanks for all the answers!
Then it is clear that public ids should be somewhat masked (make it simple), this is not something I have thought about before lately and also not seen in examples or videos, I feel missing out :)

As a hobby phper I have not got the hang of/understanding of Trongate's Authorization & Authentication yet, but I understand that it is a basis for building a user base and login system.
A login system must often be in place before you get started with what you really wanted to build, but thats another topic maybe.

Thanks again for the responses!
#8
Thank you. I'm so glad you came back.

If there's anything that you're confused with please ask for help. There's a whole bunch of people here who love to help people by answering questions. Here, there are no stupid questions and it's okay to ask questions that have already been covered elsewhere.

Therefore, please do ask as many questions as you like. Your questions help us to improve the docs. It also gives those of us who make video tutorials an opportunity to see what we need to focus on.

Cheers!
#9
Just to jump in with a quick performance tip when hashing strings...

md5 is very long in the tooth and relatively slow for an insecure hashing algo. I prefer to use XXH3 (or XXH128 if you want the same width as md5) introduced in PHP8.1: https://php.watch/versions/8.1/xxHash



Super fast, ultra low collision potential. 31.5 GB/s vs md5's 0.6 GB/s: https://xxhash.com/

Particularly good when working on many small strings, as is often the case when dealing with multiple cache file paths per request.

Also works with hash_file():

#10


That’s how simple a UUID v4 generator can be, no library needed.
However good point on make_rand_str(32); - that may just be enough for most cases.
For database indexes, going UUID especially time based ones may be worthwhile.
Internally a UUID can be represented as an integer whereas a string will be compared character by character. :)