Map data in table rows to properties in Doctrine2 objects - php

We are currently considering migrating our database code in php to Doctrine2. It seems to us that most of the things we would like the do are possible with Doctrine2. There is only one thing which we are not sure if it is possible and how we should do that. Our database model can't be changed right now because another project is using the same database. We can only change one thing at a time. Of course we are also curious how to improve the database model but that is not our main concern.
The issues is like this. We have a product table containing basic product information like this:
[product_id | code | name | description | price]
4 AS84GD Steel brush Strong steel brush..... 25.50
28 HDD21N Sand paper Sand paper for wood..... 0.40
etc
We have different users for our product which al have different extra product properties. So we have an product_extra_field table which could look like this:
[extra_field_id | name]
3 weight
4 color
9 supplier
and finally the table with the extra data product_extra_field_data
[product_id | extra_field_id | value]
4 3 280
4 4 brown
4 9 company_x
28 3 3
28 4 yellow
28 9 company_y
How do we right the necessary Doctrine2 code to get this data in one object, so we could have an object like this?
[Product]
Id : 4
Code : AS84GD
Name : Steel brush
Description : Strong steel brush.....
Price : 25.50
Weight : 280
Color : brown
Supplier : company_x
I've added a tag for Hibernate because I can read (N)Hibernate code and translate the ideas to Doctrine2.

So far, I don't think you can achieve that with mapped superclasses.
But, you could use native SQL within the doctrine result set mapping:
http://docs.doctrine-project.org/en/latest/reference/native-sql.html
Those are one of the drawbacks when mapping between objects and relational data, I mean, if you really want just one entity instead of replicating the relationships from the database.

You could create several classes:
- Product
- ExtraField
- ExtraFieldValue
With the following relations:
One Product has many ExtraFields (One To Many relation), one ExtraField has many ExtraFieldValues (One To Many relation), consedering your DB structure.
Then you have to customize your getters/setters to get only the first result of the collections (if in fact your relations are One To One)...
Don't know if I'm clear enough.

Related

Laravel eloquent for the combination of two tabels

I am new to laravel and using laravel 8. I have following tables and I am not able to understand how to establish eloquent relation between them.
Table - Fabrics
id
user_id
name
1
1
fabric 1
2
1
fabric 2
Table - Mesh
id
name
1
mesh 1
2
mesh 2
Table - Designer
id
user_id
mesh_id
fabric_id
name
1
1
1
1
designer 1
2
1
1
2
designer 2
I have done all the basic relations. Each designer has one mesh and one fabric. there is a unique combination of fabric_id and mesh_id in designer table meaning one fabric and one mesh can not have more than one row. now I want the list of fabrics with the sublist of meshes with which designers are created. basically from the designers table instead of
with(designers) I want with(meshes). Please help. Thank you in advance.
Looks like a many to many relationship problem. See this documentation
There is a good example on many to many relationship.
You have a many to many relationship between fabrics and mesh table with designer table being the intermediate table linking both tables together.
Therefore you should already have meshes relationship in your fabrics table using belongsToMany(Mesh::class) and have fabrics relationship in your mesh table using belongToMany(Fabrics::class).
You can retrieve all the fabrics and its related meshes through its relationship.
$fabrics = Fabrics::get()
foreach($fabrics as $fabric) {
$fabric->meshes
}

How to create menu and submenu using two tables?

Please help me how to create vertical menu or sub menu using these tables in PHP.
The two tables are cat(id,cat_name,main_cat_id) and main_cat(id,main_cat_name).
main_category table
id main_category_name
1 Hotels
2 Compressors
3 Apparel & Clothing
4 Automobile
5 Car Rentals
6 Mobiles & Accessories
7 Computers & Peripherals
8 Doctors
9 Education
category table
id category_name main_category_id
1 Pizza Center 1
2 2 Star Hotel 1
3 Hotel & Restaurant 1
4 5 Star Hotel 1
5 Air Compressor 2
6 Flare Nuts 2
7 Auto Accessories-Car Stereos 4
8 Automotive Parts, Components & Spares 4
9 Motorcycles, Scooters & Two Wheeler Parts 4
My policy of encouraging a prior attempt applies here. You've laid out the database, which is great, but you need to open a text editor and start on the PHP. You can do it!
Readers here could give you a working answer, but that suffers a number of drawbacks:
Firstly, they might misunderstand what you need, and so spend a long time on something that does not help you.
Secondly, there are several million people out there that would like people to work for them for free, and we'd be here until Doomsday if we did that.
Finally, if you get a working answer with no personal research, you might not learn anything.
Here's a suggested plan of action:
Install WAMP/MAMP/LAMP on your computer
Set up your database structure and test data in a MySQL instance on your development machine
Write some PHP code to connect to the database and run a test query on it, dumping the data in a web page
Once that works, modify the query to read the categories, using an ORDER clause to get them in the right order
Now you have enough information to create a menu. Look up the format of a <select> tag using <option> tags, each of which contains the name from your database. You'll need a value attribute for each one - this is usually the id from each row of the database
Wrap the above in a <form>
From here, you can expand your menu to contain a second level. The simplest way of doing that is to research the <optgroup> tag - much under-used, in my opinion. This allows you to set up a two-level menu that is intuitive for users and simple to read values from in code.
Give that a go?

Designing Flexible SQL Schema [for Quests]

What would be an efficient way to store "Quests" in an SQL database? Let's say the context is RPG. (Here was a previous question: How to store Goals (think RPG Quest) in SQL)
To summarize a Quest may be a combination of the following:
Discover [Location]
Kill n [MOB Type]
Acquire n of [Object]
Achieve a [Skill] in [Skillset]
All the other things you get in RPGs
The answer listed out in the link was:
For the Quest table:
| ID | Title | FirstStep (Foreign key to GuestStep table) | etc.
The QuestStep table
| ID | Title | Goal (Foreign key to Goal table) | NextStep (ID of next QuestStep)
I actually think it's pretty neat, but I have two things I would like to add:
Let's say I want to create it so that a quest can only be active only on certain days (e.g. M W F only) and/or active only at a certain time span (e.g. Halloween). What would be the ideal way of doing this?
Another thing: Let say I want to have a quest with two steps and a quest with 8 steps. We can create a table that is 8 columns wide but we would have lots of empty space. And what if the stars align and I needed an 9 step-wide quest?
The QuestStep table actually has a NextStep, sort of like a linked list, but what about Quests that you can do out of order?
P.S: As you can see it is potentially read-heavy, and the schema is potentially... non-schematic. Is NosSQL a vying option? (Redis seems memory only, so I'll more likely go with MongoDB)

Database design: implementing several types of the same entity

I'm coding a Classified Ads web application. The application has several types of Ads:
General ads(electronics, toys, pets, books...)
Real estate (houses, apartments, terrains...)
Vehicles (motocycles, cars, vans, trucks...)
Each type has several common fields (id, title, description) and also some that are exclusive to its kind:
General Ads (no exclusive fields)
Real estate (area, type-of-property...)
Vehicles (type-of-vehicle, cubic-capacity, kilometers...)
What is the most recommended approach to this situation?
A table that contains all fields and leave empty the fields that
don't apply to the current recordset.
A main table with the fields common to all Ads, and an additional table for each type of Ad that has exclusive fields.
One table for each type of Ad.
Other
I would build a solution depending on various criteria :
If you believe the table will be large in the future (a lot of ads to be published), you may want to minimize the number of JOINs for better performance => option 1. "one table with empty fields when not relevant to ad type"
Previous comment applies especially if your data storage cost is low.
If you have to query the data against certain field values (e.g. house size, car kilometers), you might avoid the solution described by phpalix (ad_type | property | value) or Andy Gee since your SQL syntax will be a nightmare, and prefer to have all your data in the same table (again).
If there are A LOT of custom fields per ad type, you might prefer to separate each ad type in their own table, for easier maintenance and data storage optimization. Then you can either JOIN or UNION to query your ads lists.
I'll add to my answer if i think of something else.
You can normalise (a table for the abstract concept and a table the the specialised one) or denormalise (a table with all the fields)
As always, the choice must be done according to the cost of each solution, reprensented by the speed of the queries (normalised model means more joins (buffer/cpu) whereas denormalised more disk reads usually because the columns are sometimes retrieved when it is not necessary) or the storage required in both cases.
All solutions are acceptable and a matter of preference, performance, complexity and design needs. The terms for what you are discussing are Table-Per-Type, Table-Per-Class and Table-Per-Hierarchy. If you google on these you are guaranteed to get a ton of Entity Framework results, but the underlying design considerations are much the same.
For flexibility I would have all the field in a separate table then allow the assigning of each field to each ad type. This would also allow you to add and remove fields easily at a later date.
Each field may have different types of data so this information should also be in a separate table.
Something like this (not very clear sorry)
Table: fields
field_id, field_type, field_name
1 1 title
2 1 price
3 2 size
4 3 description
5 1 square meters
Table: field_types
field_type_id, type
1, textbox
2, select_box
3, text_area
Table: field_data
field_data_id, ad_id, field_id, field_type_id, field_data
1 1 1 1 Cool t-shirt
2 1 2 1 5.99
3 1 3 2 L,XL,XXL,XXXL
4 1 4 3 Some description
5 2 1 1 Nice house
6 2 2 1 250000
7 2 4 3 Some description
8 2 5 1 1024sq/m
Table: ad_types
ad_type_id, ad_type_name, fields
1 general 1,2,3,4
2 real_estate 1,2,4,5
Well, store the values in columns and not in rows, so create a table and have 3 columns:
ad_type, property, value
define your properties for each type of ad and query the ad type for its fields.
Hope that helps

Best way to store custom parameters per asset

I have a table where I have information about each asset I have (Laptop, Screen, Desktop, Scanners, etc..). I also have another table where I have custom column for each asset (so for a specific desktop I can have a custom column called "Color")... quick shematic :
Assets Table
AssetID Description
---------------------------
1 Desktop HP79801
Assets Custom Column
AssetID Column1 Column2
-----------------------------------
1 Color BluRay ?
Now I want to store the value for each column. The way I currently do it for each unit is :
AssetID UnitID Column1 Column2
-----------------------------------
1 1 Blue Yes
1 2 Blue No
1 3 Black No
1 4 Blue Yes
Now my question, is there a more efficent way to do this and how can I increase the number of column to infinity in an efficent way also ? Is it possible ?
In the end, how to store custom product attributes with effecienty ?
In short, yes.
What you have there isn't scalable in the slightest. What you want is to have a table for your assets, a table for the custom parameters and a "link" table. Then, enter multiple values into your link table rather than multiple columns.
As an example:
Assets Table
AssetID Description
---------------------------
1 Desktop HP79801
Attributes Column
AssetAttr Column1
-----------------------------------
1 Color
2 Size
Link table
AssetID UnitID AttrId AttrValue
-----------------------------------
1 1 1 Blue
1 1 2 Big
1 2 1 Orange
1 2 2 Giant
If your attributes are all model specific though, you may also want to add a AssetId column to your assets custom column, but I wouldn't personally do that unless none of your assets at all shared attributes.
You may also want to tag this further. You may want to annotate your attributes table with a data type, and maybe have another table related to the attributes table holding the possible data values, then, in your link table, insert the ID of the entry from the aforementioned table.
Another solution would be to use a schema less db altogether. My favorite is Mongo. Another option would be CouchDB or one of the many key-value databases out there.
Not to start a noSQL war here but these databases handle situations like that a lot more gracefully - a single document could store all that data and be retrieved without any joins or views.

Categories