I read about an inheritance feature in PostgreSQL that seemed pretty neat. Unfortunately I am forced to use MySQL. How would you do something similar in a clean way?
Say you for example had the two following classes that you want to work with:
User
˪ Id
˪ Name
˪ Password
Employee : User
˪ Pay
How would you store those in a MySQL database so that they can be fetched from for example PHP in a fairly clean way? I need to for example be able to fetch all users including employees, only employees, find if a user is also an employee, et cetera.
Looking for general advice and not a specific solution to this case. I for example see that I could simply add a nullable Pay column to a Users table, but I don't really like that idea as it would quickly become very messy if more sub-classes were needed.
Add a field to Employee which is a foreign key to User. You'd still have to perform a join across the tables, but it's better than nothing.
Related
I'm having a bit of a problem figuring out a good way to manage row-level permissions for an API i'm building.
Let's assume three tables:
List
Notes
Note comments
Notes references the list it belongs to in a list_id column
Note comments references the note it belongs to in a notes_id column
I want to be able to load all the comments that a user has access to at once. If the user has access to a list i'd like the user to also have access to the notes referencing that list, as well ass the note comments referencing any of those notes.
Is there any specific good practice for this?
Thanks!
There are several... But i'd go for proven complete solutions like using and ORM of sorts... (doctrine2 comes to mind)
But you could just write your own with some simple joins ;)
I have a site that has different type of products with different specifications for each of them.
I want to be able to use only one products table with a set of columns but because columns are different depending on what type, I have to create multiple products table catering for each type. This I think is time consuming and not really effective way to manage as an ongoing solution.
Is there a good way to manage this type of scenario with the database?
I'm using Cakephp as the framework.
Normalise your data structure: for example, have a product_info table (with FK into the products table) that contains columns key and value to express additional information about each product.
Martin Fowler lists three general approaches.
Single table - Putting all the columns in one table and only using the ones you need (this sounds the closest to what you have)
Class table - All classes have their own table storing data specific to that class (with the same primary key in every relevant table)
Concrete table - The same as above, but only concrete classes have tables, not abstract ones.
Single table is the simplest unless you have a good reason not to - just have all possible fields there, and only use the ones you need in each class. You do have the disadvantage of not being able to enforce NOT NULL; if this matters, either make a custom constraint depending on the type of object, or use option 2 or 3.
I wrote about using the EAV model with cake a little while ago, I think this post might be helpful, but slightly outdated.
http://nuts-and-bolts-of-cakephp.com/2010/07/27/keyvalue-tables-and-how-to-use-them-in-cakephp-1-3/
Also, this could be very helpful for your particular question... Please take a look and study some concepts in Magento (a very popular PHP-based ecommerce framework) makes heavy use of EAV schemas and does a nice job of indexing and flattening the data.
You can certainly gain a lot of interesting perspective on EAV implementation. Whether you love it or not is a different story :)
Currently, I am dealing with database structure and I would like to get a piece of advice.
I have 2 objects: banner and ad.
For them I may create banner table and ad table, which will hold all the info about each entity. As main advantage I see that everything related to 1 entity is in this entity table.
On the other hand, I may some table like:
entity_properties.
It will hold value_id entity_id property value. The main advantage is that for entities I need only some basic fields, other fields can be put in this table.
But I am not sure which is the better practice and performance?
Thanks in advance.
For the sake of normalization it is always better to have 1 table per 1 entity. Normalization is an aim or an approach to minimize redundancy and dependency in relational databases . In your case banner and ad are different entities. For now it seems that you can use them in same table. So "redundancy" is not the case. However, what if you want to add some additional fields later?
In addition code complexity and readability is another issue. For instance, when you add different types of object in same table you need to add an internal logic to differentiate them in your code. This means you have complex and probably less readable code.
That depends on the exact use of your system and the attributes/values you're trying to store.
As I see it, I think it would be good to save the important and required information in one table, your 'ad' table, and the rest in the 'ad_entities' table, with an ad_id, entity_name, entity_value, or something similar for your application.
This is a good performance choice since you'll be able to get all the information about the current Ad or all Ads using just one quite simple query, which your objects can easily figure out.
Let's say I have three tables: users, books, and users_books.
In one of my views, I want to display a list of all the books the current user has access to. A user has access to a book if a row matching a user and a book exists in users_books.
There are (at least) two ways I can accomplish this:
In my fetchAll() method in the books model, execute a join of some sort on the users_books table.
In an Acl plugin, first create a resource out of every book. Then, create a role out of every user. Next, allow or deny users access to each resource based on the users_books table. Finally, in the fetchAll() method of the books model, call isAllowed() on each book we find, using the current user as the role.
I see the last option as the best, because then I could use the Acl in other places in my application. That would remove the need to perform duplicate access checks.
What would you suggest?
I'd push it all down into the database:
Doing it in the database through JOINs will be a lot faster than filtering things in your PHP.
Doing it in the database will let you paginate things properly without having to jump through hoops like fetching more data than you need (and then fetching even more if you end up throwing too much out).
I can think of two broad strategies you could employ for managing the ACLs.
You could set up explicit ACLs in the database with a single table sort of like this:
id: The id of the thing (book, picture, ...) in question.
id_type: The type or table that id comes from.
user: The user that can look at the thing.
The (id, id_type) pair give you a pseudo-FK that you can use for sanity checking your database and the id_type can be used to select a class to provide the necessary glue to interact the the type-specific parts of the ACLs and add SQL snippets to queries to properly join the ACL table.
Alternatively, you could use a naming convention to attach an ACL sidecar table to each table than needs an ACL. For table t, you could have a table t_acl with columns like:
id: The id of the thing in t (with a real foreign key for integrity).
user: The user the can look at the thing.
Then, you could have a single ACL class that could adjust your SQL given the base table name.
The main advantage of the first approach is that you have a single ACL store for everything so it is easy to answer questions like "what can user X look at?". The main advantage of the second approach is that you can have real referential integrity and less code (through naming conventions) for gluing it all together.
Hopefully the above will help your thinking.
I would separate out your database access code from your models by creating a finder method in a repository class with an add method like getBooksByUser(User $user) to return a collection of book objects.
Not entirely sure you need ACLs from what you describe. I maybe wrong.
This isn't much of an issue with MySQL per-se.
The Full Story
I'm writing a very small PHP framework. It isn't like existing frameworks where they force you to use a certain methodology. It isn't either like a CMS framework. Trust me, I've seen Zend framework and I've used CMSes like Joomla and WordPress extensively, none of them come close to what I'm doing.
Introducing The Issues
I'm writing the Database abstraction part. You get class methods like ::table_exists() etc.
It is designed in a way that people can easily add different database classes and use them instead (eg; mysql, mssql, oracle, flatfile...).
They simply need to write a class which satisfies a base abstract classes'.
The Real Issue
I'm writing the functionality for ::table_create(), but have one main problem: MySQL doesn't like empty tables (ie, without a column).
I have several proposed fixes:
For each new table, create a commonly used column, such as 'id' (type=INT)
For each new table, create a temp column which doesn't use any space as much as possible (perhaps a boolean column?)
Somehow delay table creation until at least one column can be created
This approach is most certainly new, and I'd like to here some unbiased comments about it (anything on the lines of "but no one does it that way" won't do).
Well I would either go with option 1), Adding a generic ID column, which you might find you need anyway, or with option 3) Delaying the table creation. I'm assume after they call ::table_create() they will be calling table_add_col(), etc. So just delay creation until there is at least one column, OR until they actually try and use the table for the first time.
Your proposed fixes look quite good. But I would recommen them in a diffrent order. If you are able to delay the creation, tht's probably the best. My second favorite would be to have a table with only an ID, although you might be delete this column, if you want to create a many-to-many relations table with two foreign keys only.
last of your points.
its really very strange what you are doing here. creating tables on the fly? dynamically or something?
well... whatever you are trying to accomplish. you should have a look at document/object oriented databases like couchdb http://couchdb.apache.org/ ! you can create a document and dynamically add whatever fields you want. those are the closest thing to your "columns"
but as you like it...
your first attempt is ugly because it might lead to conflicts.
the second attempt is clumsy. but if you do so create a col with uniqueprefix_random so you can delete it afterwards.
but its well... i dunno what to say about that.
theird approach seems the only senseful!