Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

lee__mason's avatar

table structure for extendable app

I'm currently developing an app which will be extendable via "plugins".

the idea is basically the core app will have users and a users table.

now say for example i wanted to add a plugin which adds newsletter signup, or billing to individual users.

im in need of some help regarding how to reflect this in the database.

i see three options:

  1. foreach plugin add a new db table which references the user id

  2. have the core app build a user meta table which plugins can use (i.e. wordpress get/update_user_meta)

  3. allow each plugin to alter the core user table via migrations

this is my dilemma.

  1. pretty simple, but could mean multiple tables with maybe 1,2 columns plus means extra queries when fetching the data for any plugin.

  2. pretty simple again with only 1 extra table, but still multiple queries to access the data

  3. no extra queries, less tables, but my gut is telling me this may be bad practise to suggest plugins should alter core tables.

i will be using eloquent so number 2 can be handled with a has many relationship pretty easily. plus if a plugin was sufficiently large it could still create its own table.

number 3 is what i really want to get peoples views on.

i have another example which may help explain a little better, take jefferys billing tutorials.

say i have a plugin which adds billing for stripe and paypal, but could also have other payment gateways.

the app doesnt know by default this plugin will be used, so the core user table would not have a stripe or paypal subscription id column.

if however the user activates the billing plugin, should the plugin alter the core user table to add a stripe/paypal column?

and if another payment gateway is added should any new columns be added to cater for this.

if we take option 1 we end up with a table that just has user_id|stripe|paypal

with option 2 we have a row in the user meta table like: user_id|stripe_id|value and user_id|paypal_id|value

with option 3 we alter the user table to add two columns strip_id|paypal_id and whenever the user model is accessed the values are already fetched.

any opinions welcome.

0 likes
3 replies
MThomas's avatar

First of all I suspect that for each client the app will be installed on a seperate location.

I would definitly opt for option 1. This is most logical if you stick to a relational database and normalize the fields.

Regarding your second option, I would not worry about the extra queries, but the size of the table can grow quickly and when it grows you will lose sight of how your data is strucktered,

Option three I am no fan of eighter, running migrations on production sould be limited. What you could do for the stripe and paypal case is the following. If for your implementation you need the information stored in the users table than you can add these columns by default to the users table. But best would be implementing it in such a way that you don't need to add these columns to the user table in your case.

lee__mason's avatar

thanks for your insight, was probably just over thinking it i think.

MThomas's avatar

Your welcome.

You might by default create al the tables that are availible for all (even unused) packages. This will limit structural changes to the database even more.

Please or to participate in this conversation.