简体   繁体   中英

Best way to store a category name from php in a mysql table

My project is a website written in php & js that use a mysql database.

I need to store an item with its "category" or "type" (couldn't find a better name for that). Each item can only have one category.

Each category has a "name" (a sort of id) used by the php and javascript code, like "hat".

These "names" are hard-coded in the php/javascript code. They are not user-defined. There's a known list of them. There can be new "names" with new versions of the application, and eventually some can be removed.

Here are the solutions I considered:

Second table with a one-to many relation

This is the solution I'm currently using.

The database would look something like this:

items

  • INT id (primary)
  • INT category_id (index)

categories

  • INT id (primary)
  • VARCHAR name (unique)

Downsides (for me):

  • I have to store the categories in the database. For the moment I have a sort of seeding that adds all my categories to the database. But that way the data is in at least two places (DRY !), and I have to update the seeding script each time I do a modification
  • When I do a query, I have to use two tables, because the php code only knows the "name"
  • When I insert a record I have to do a subrequest to find the category id first from the "name"

Mysql enums

The database would look something like this:

items

  • INT id (primary)
  • ENUM category (index) [hat, shirt, socks, ...]

It has the advantage to remove the two-tables query of the first solution, but the data is still duplicated, and more heavily bould to the database than ever.

String field in the items table

The database would look something like this:

items

  • INT id (primary)
  • VARCHAR category (index)

The category name is stored directly in the "items" table, with a index. From the query view I have the impression that the index will act the same way that the second table I used previously (with the advantage of querying only one table and one index instead of two tables and two indexes)

So, Problem...

What is the best way to do it, in term of performances and/or maintainability ? Is there another better way to do it ?

Having integrity constraint would be good but not necessary. (I can manage this problem in another way)

I have found the following thread: php mysql - should i add the field "category-name" to a table or not? , but it was about a many-to-many relationship and looks like it was a variable list of categories. So it doesn't really apply to my case.

It depends,

How many categories will you have, how often will you need to update them?

I've taken the approach before where I added Enum, but also wrote a static method in a class and stored the valid names there

class Item{


    public static function get_categories()
    {

        // only works in php >=5.4 otherwise use return array('Category1'...);
        return [
          'Category1' => 'Category1',
          'Category2' => 'Category2',
          'Category3' => 'Category3'
        ];
    }

}

Doing the above you can easily get access to the array by Item::get_categories(), which should correspond to the values in the ENUM field in the database. If you need to add more categories, add them to the database and then to this function. You can use this to validate the users choice and generate the javascript options.

However!!!!

You mention a seeding that populates your table, this wouldn't be able to easily update your ENUM for you.

I'd use an ENUM, because

1). It's easy to setup 2). It's slightly easier than joining the two tables (but JOINS are ace when you learn them) 3). If you used a secondary table you'd (as you pointed out) have to lookup the value from that table first, and then insert, or if the category was used in a dropdown, use the category id and it's name to populate the dropdown (i'd do it this way)

Final thought

The performance of both the ways (lookup table, and ENUM) you would barley even notice the difference unless your site is very very busy. You'd still have to update the categories table with each version both ways, but it would be slightly easier to USE an INSERT statement instead of a ALTER TABLE

Whichever way you chose, if you don't like it, it would be quite easy to update your code.

Hope this helps, and good luck

Remember Keep It Simple Stupid KISS

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM