Handling table attributes/properties using CakePHP and MySQL - php

First of all, happy new year :-)
I think my question would be obvious for good programmers but I didn't manage to find an answer.
Let's say I have a Customer table and I would like this Customer to have some attributes (properties). I don't want to add a new field in the Customer table every time I will add a new attribute. Moreover, customers don't have the same number of attributes.
All that we know is each attributes is known in advance (some day, I will add a 'referer', 'age', 'type_of_prefered_food' .... attributes that is not mandatory, so customers may fill the information or not).
My question is, which is the best way to manage it using CakePHP 3 and MySQL ?
Having a Customer HasMany Attributes (If think in this case I have to have a constant list of each properties ID)
OR
Having a Customer BelongsToMany Attributes (so, through a relation table)
Knowing that, which is the best :
Having a attribute ID referenced by an INTEGER or a STRING ?
How to retrieve a specific property ...
My question is mostly CakePHP oriented, I want to know if one approach is easier to work with. Is there a CakePHP Tools/function/library that will help me to retrieve/add/edit easily attributes to a specific Customer ?
The best question I managed to find is : How to pivot a MySQL entity-attribute-value schema
Thanks in advance for those having the time to respond.

Related

Php: use data from a join table with mvc

Heya I am novice web dev or actually I am still in education.
I got this situation Where I have 3 tables lets say : Students, Groups and a join table Student_group.
I put my data from Students in the student model and from groups I put its data in the Group Model so I can use it my application. But I store a date in the Student_group table because I need to know when a student changed from a group.
So my question is in which model do I put this date? Do i need to make a new model for the combined tables or do I need to add another attribute to the student model?
Thanks in advance ;D
That depends. Will the student be in many groups, or one?
If one (one to one relationship), you can decide where to put it. The column could be in either the Student table, or the Student_group. In this case, though, it may be advisable to flatten the data and simply add group columns in your Student table. You decide that as well - if it seems unnecessary to have a join for a one to one relationship (usually it is, not always), then flatten it. In either case, the data should stay in its respective model. That said, you should use the Student model if you handle it in the Student table.
If many (one to many relationship), I'd advise putting it in the Student_group table and leaving it in that model as well.
All in all, the model should be a direct reflection of the data it's representing. You could make some methods inside your Student model to make it easier to get the date, for example. However, I'd personally handle that date inside of the proper model, Student_group. As mentioned, the model should be a direct representation of the data. Again, though, there's nothing wrong with making things a bit easier by creating some methods that help out the developer.

How do i link database relationship with the following information?

I have been relentlessly trying to edit my database relationships but to no avail. Here is the scenario:
i have an inventory table. an inventory can be classified into 2 categories(technical eg. guns, radios and general eg. uniforms). i was hoping there could be a way for me to add details(from different tables eg. technical_inventory_table and general_inventory_table) to the inventory table through the category since the two categories have different fields. is there any way for me to do that? please do note that a technical inventory will be listed individually since a single item will have a serial number attached to it.
or does the answer provided here - https://dba.stackexchange.com/questions/33099/storing-different-products-and-joining-on-table-names - be an already good solution for my problem? i would like to avoid creating a table where it will be made up of what usually are the fieldnames as described in the link to prevent confusion within my team.
thanks for any help in advance

Data model for subscriptions, single purchase products and variable services

I am designing a database for a system that will handle subscription based products, standard one off set price purchase products, and billing of variable services.
A customer can be related to many domains and a domain may have many subscriptions, set priced products or billed variable services related to it.
I am unsure whether to seperate each of these categories into their own 'orders' table or figure out a solution to compile them all into a single orders table.
Certain information about subscriptions is required such as start date or expiry date which is irrelevant for stand alone products. Variable services could be any price so having a single products table would mean I would have to add a new product which may be never used again or might be at a different cost.
What would be the best way to tackle this, and is splitting each into seperate order tables the best way?
Have you looked at sub-typing - it might work for you. By this I mean a central "order" table containing the common attributes and optional "is a"/one-to-one relationships to specific order tables. The specific order tables contain the attributes specific only to that type of order, and a foreign key back to the central order table.
This is one way of trying to get the best of "both" worlds, by which I mean (a) the appropriate level of centralisation for reporting on things common and (b) the right level of specialisation. The added nuance comes at the cost of an extra join some times but gives you flexibility and reporting.
Although I am a little biased in favour of subtypes, some people feel that unless your order subtypes are very different, it may not be worth the effort of separating them out. There is some seemingly good discussion here on dba.stackexchange as well as here. That being said, books (or chapters at least) have been written on the subject!
As with any data model, the "best" way depends on your needs. Since you don't specify a lot of details regarding your specific needs, it's difficult to say what the bets model is.
However, in general you need to consider what level of detail is necessary. For example if all subscriptions cost the same and are billed on the 1st of the month, it may be sufficient to have a field like is_subscription ENUM ('Y', 'N') in your orders table. If billing dates and prices for subscriptions can vary however, you need to store that information too. In that case it may be better to have a separate table for subscriptions.
Another consideration is exactly what an "order" represents in your model. One interpretation is that an order includes all the purchases included in one transaction, including both one-off purchases, variable services and subscriptions. A completed order would then result in a bill, and subscriptions would be automatically billed on the proper day of the month without a new order being made.
You should aim to have one database design that is not hardwired into specifics regarding its contents, and if it does (have to) it does in such a way that it seperates the specialization from the core DB design.
There are certain fields that are common for each order. Put these in one table, and have it refer to the other rows in the respective (specialized) tables. Thats DB normalization for you.
You could have main table contain ID, OrderID, ItemType, ItemID when ItemType determines the table ItemID refers to. I advise against this, but must admit that i use this sometimes.
Better would be to have these tables:
Clients: ID, Name, Address, Phone
Sellers: ID, Name, CompanyAlias
Orders: ID, ClientID, SellerID, Date, Price
OrderItems: ID, OrderID, DiscountAmount, DiscountPercentage,
ProductDomainID, ProductBottleID, ProductCheeseID, ..
Now OrderItems is where the magic happens. The first four fields explain themselves i guess. And the rest refers to a table which you do not alter or delete anything ever:
Products_Cheese ID, ProductCode, ProductName, Price
And if you do need a variant product for a specific order add a field VariantOfID thats otherwise NULL. Then refer to that ID.
The OrderItems table you can add fields to without disturbing the established DB structure. Just constrict yourself to use NULL values in all Product*ID fields except one. But taking this further, you might even have scenario's where you want to combine two or more fields. For example adding a ExtraSubscriptionTimespanID or a ExtraServicelevelagreementID field that is set alongside the ProductCheeseID.
This way if you use ProductCheeseID + ExtraSubscriptionTimespanID + ExtraServicelevelagreementID a customer can order a Cheese subscription with SLA, and your database structure does not repeat itself.
This basic design is open to alterative ideas and solutions. But keep your structure seperated. Dont make one huge table that includes all fields you may ever need, things will break horribly once you have to change something later on.
When designing database tables, you want to focus on what an entity represents and having two or more slightly different versions of what is essentially the same entity makes the schema harder to maintain. Orders are orders, they're just different order types for different products, for different customers. You'd need a number of link tables to make it all work, but you'd have to make those associations somehow and it beats having different entity types. How about this for a very rough starting point?
What would be the best way to tackle this, and is splitting each into seperate order tables the best way?
That depends. And it will change over time. So the crucial part here is that you create a model of the orders and you separate the storage of them from just writing code dealing with those models.
That done, you can develop and change the database structure over time to store and query all the information you need to store and you need to query.
This for the general advice.
More concrete you still have to map the model onto a data-structure. There are many ways on how to solve that, e.g. a single table of which not all columns are used all the time (flat table), subtype tables (for each type a new table is used) or main table with the common fields and subtype tables containing the additional columns or even attribute tables. All these approaches have pros and cons, an answer here on Stackoverflow is most likely the wrong place to discuss these in full. However, you can find an insightful entry-level discussion of your problem here:
Entity-Attribute-Value (Chapter 6); page 61 in SQL Antipatterns - Avoiding the Pitfalls of Database Programming by Bill Karwin.

Symfony2 / Doctrine model join single table to multiple other tables by related ID and type

I'm trying to work out the model for a fairly simple application, but I haven't been able to find good information regarding my idea for dealing with user comments. I was thinking that I could have a Comment table, with "related ID" and "related type" fields. These fields would be the composite foreign key back to whatever other table I wanted to link to. For example, you could leave a comment about a User, or a Location, or really any other entity. Is this kind of design possible in Symfony2/Doctrine? If so, is there a good example to reference somewhere?
This is what you're looking for http://doctrine-orm.readthedocs.org/en/2.0.x/reference/inheritance-mapping.html
You'll need to use a discriminator field using Single Table Inheritance or Class Table Inheritance

database table design for some unknown data

So, not having come from a database design background, I've been tasked with designing a web app where the end user will be entering products, and specs for their products. Normally I think I would just create rows for each of the types of spec that they would be entering. Instead, they have a variety of products that don't share the same spec types, so my question is, what's the most efficient and future-proof way to organize this data? I was leaning towards pushing a serialized object into a generic "data" row, but then are you able to do full-text searches on this data? Any other avenues to explore?
split products and specifications into two tables like this:
products
id name
specifications
id name value product_id
get all the specifations of a product when you know the product id:
SELECT name,
value
FROM specifications
WHERE product_id = ?;
add a specification to a product when you know the product id, the specification's name and the value of said specification:
INSERT INTO specifications(
name,
value,
product_id
) VALUES(
?,
?,
?
);
so before you can add specifications to a product, this product must exist. also, you can't reuse specifications for several products. that would require a somewhat more complex solution :) namely...
three tables this time:
products
id name
specifications
id name value
products_specifications
product_id specification_id
get all the specifations of a product when you know the product id:
SELECT specifications.name,
specifications.value
FROM specifications
JOIN products_specifications
ON products_specifications.specification_id = specifications.id
WHERE products_specifications.product_id = ?;
now, adding a specification becomes a little bit more tricky, cause you have to check if that specification already exists. so this will be a little heavier than the first way of doing this, since there are more queries on the db, and there's more logic in the application.
first, find the id of the specification:
SELECT id
FROM specifications
WHERE name = ?
AND value = ?;
if no id is returned, this means that said specification doesn't exist, so it must be created:
INSERT INTO specifications(
name,
value
) VALUES(
?,
?
);
next, either use the id from the select query, or get the last insert id to find the id of the newly created specification. use that id together with the id of the product that's getting the new specification, and link the two together:
INSERT INTO products_specifications(
product_id,
specification_id
) VALUES(
?,
?
);
however, this means that you have to create one row for every specific specification. e.g. if you have size for shoes, there would be one row for every known shoe size
specifications
id name value
1 size 7
2 size 7½
3 size 8
and so on. i think this should be enough though.
You could take a look at using an EAV model.
I've never built a products database, but I can point you to a data model for that. It's one of over 200 models available for the taking, at Database Answers. Here is the model
If you don't like this one, you can find 15 different data models for Product oriented databases. Click on "Data Models" to get a list and scroll down to "Products".
You should pick up some good design ideas there.
This is a pretty common problem - and there are different solutions for different scenarios.
If the different types of product and their attributes are fixed and known at development time, you could look at the description in Craig Larman's book (http://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=sr_1_1/002-2801511-2159202?ie=UTF8&s=books&qid=1194351090&sr=1-1) - there's a section on object-relational mapping and how to handle inheritance.
This boils down to "put all the possible columns into one table", "create one table for each sub class" or "put all base class items into a common table, and put sub class data into their own tables".
This is by far the most natural way of working with a relational database - it allows you to create reports, use off-the-shelf tools for object relational mapping if that takes your fancy, and you can use standard concepts such as "not null", indexing etc.
Of course, if you don't know the data attributes at development time, you have to create a flexible database schema.
I've seen 3 general approaches.
The first is the one described by davogotland. I built a solution on similar lines for an ecommerce store; it worked great, and allowed us to be very flexible about the product database. It performed very well, even with half a million products.
Major drawbacks were creating retrieval queries - e.g. "find all products with a price under x, in category y, whose manufacturer is z". It was also tricky bringing in new developers - they had a fairly steep learning curve.
It also forced us to push a lot of relational concepts into the application layer. For instance, it was hard to create foreign keys to other tables (e.g. "manufacturer") and enforce them using standard SQL functionality.
The second approach I've seen is the one you mention - storing the variable data in some kind of serialized format. This is a pain when querying, and suffers from the same drawbacks with the relational model. Overall, I'd only want to use serialization for data you don't have to be able to query or reason about.
The final solution I've seen is to accept that the addition of new product types will always require some level of development effort - you have to build the UI, if nothing else. I've seen applications which use a scaffolding style approach to automatically generate the underlying database structures when a new product type is created.
This is a fairly major undertaking - only really suitable for major projects, though the use of ORM tools often helps.

Categories