PHP & MySQL Tagging system logic - php

I am a beginner developer and i would like to ask some advice.
I am currently building a platform where people will be allowed to upload images and tag them.
I was reading through some articles with the following structure to store tags
Storing Logic 1
| photo_id | name | tags |
| 1 | some photo | flower, sun. island, beach |
| 2 | some photo2 | hawaii, travle. surf |
Lot of people said this is not such a good idea
So my logic.
I was reading around about Many-to-Many relations and i came up with this logic
Tags table
| tag_id | name |
-----------------------
| 1 | flower |
| 2 | hawaii |
| 3 | surfing |
| 4 | island |
| 5 | travel |
Photos table
| photo_id | name |
---------------------------
| 1 | some photo |
| 2 | some photo2 |
Relation table
| tag_id | photo_id |
---------------------------
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
I have chosen to use Laravel framework to make the development easier
But my problem is with logic 2 and what i am scared of is it will generate a huge load time.
Because there will be no default just user based tags i thought about the following logic.
User uploads the image with tags, before image is saved, check if the actual tags exsit if not save it, than return tags_id and save it to the relation table with photo_id
So i have 2 questions
Which logic is better and why?
If logic 2, is it good the way i thought it up? and should i worry about the load time in the future when lot of tags will be there?
thank you

I would go with the second one. I wouldn't worry about load times. You can easily get the categories with joins.
However, you should add an id column on the relation table so that multiple images can share a category.

In your second example, your relation table should have indexes, so that when you look for all the tags based on a specific photo_id, the answer will be rapidly returned.
See also Foreign Keys
In your relation table, tag_id is a foreign key into your tag table and photo_id is a foreign key into the photo table. Tags may have a relationship to more than 1 photo and a photo may have a relationship to more than one tag.
Similarly the names of your tags (and photos) should also be indexed for rapid searching.

Related

Database model for a multilanguage translation module

I need to design a db model for a backend module where user can translate page content into multiple languages. The things that will be translated are basic words, phrases, link names, titles, field names, field values. They should also be grouped so i can find them by group name. For example if there is a select field on page with different colors as options then i should be able to select all of them by group name.
So here is what i have at the moment:
lang
+----+---------+
| id | name |
+----+---------+
| 1 | english |
| 2 | german |
+----+---------+
lang_entity
+----+------------+-------------+-------+-------+
| id | module | group | name | order |
+----+------------+-------------+-------+-------+
| 1 | general | | hello | 0 |
| 2 | accounting | colorSelect | one | 1 |
| 3 | accounting | colorSelect | two | 2 |
| 4 | accounting | colorSelect | three | 3 |
+----+------------+-------------+-------+-------+
lang_entity_translation
+----+---------+----------------+-------------+
| id | lang_id | lang_entity_id | translation |
+----+---------+----------------+-------------+
| 1 | 1 | 1 | Hello |
| 2 | 2 | 1 | Guten tag |
| 3 | 1 | 2 | One |
| 4 | 2 | 2 | Ein |
| 5 | 1 | 3 | Two |
| 6 | 2 | 3 | Zwei |
| 7 | 1 | 4 | Three |
| 8 | 2 | 4 | Drei |
+----+---------+----------------+-------------+
So lang table holds different languages.
Table lang_entity has entities that can be translated for different languages.
Module row is just to group them by page modules in the backend translating module. Also this gives me possiblity to have entities with same name for different modules.
Group as mentioned is needed for selects and maybe some other places where multiple values are going to be used. This also gives me an option to allow user to add and order entities in one group.
And table lang_entity_translation holds the translations for each entity in each language.
So my question is are visible flaws in this kind of a design? Would you reccomend something different?
Also a bonus question: I really dont like the lang_entity table name, do you have a better idea of a table name that would hold all the words/phrases that are translated? :)
Edit: similar, but not a duplicate. The linked question is about translating dynamic products and having a seperate table for each translated type. Im talking about translating whole page content, including groups in a single table.
I don't understand the order column of lang_entity, but then I probably don't need to.
The setup looks sane, but make sure you add foreign key constraints from lang_entity_translation to language and lang_entity.
As for naming, I would call the table phrase or translatable.
We had similar situation. This was 7 years before.
We had different column for different language. Like for name we had
Name_Eng,Name_Ger,Name_Spa .We had 7-10 language.
We had common id for name for all language.
Based on the Language selection from UI we passed the language code to Back end In the Stored proc it was appended to the column Name
Example, we will be passing "Eng" if English is selected and we form the column name as Name_Eng and fetch the data. we were using dynamic query.

mysql performance and security related issue

I get some issues when i implement product_description table with language .
my process is that i have default table product_description_en to store description and when a client installs new language (Chinese) the php script will create new table product_des_ch and then put the all default data(from the English table) in to the newly created table.then the client can update .
My problems are
Is it a security issue that we create the table dynamically while installing new language
2.If we use same table for all languages(the records will be around 500,000) then are there any per performance issues
3.what is the best way for large amount of records to store , i mean same table or separate tables.
Thanx
Az
Updated:
This is sample product_description table structure for English table and Japan .What you think about this table(we store the all records in a same table and when the client inserts new record for different language only inserting new records ) ,Any feedback please ?
+---------------------------------------------------------------------------+
| product_id | name | desc | meta_name | meta_desc | key_words | lan_code |
+---------------------------------------------------------------------------+
| 1 | A | D| m1 | m_d1 | k1 | en |
+---------------------------------------------------------------------------+
| 1 | A | D| m2 | m_d2 | k2 | jp |
+---------------------------------------------------------------------------+
Basic RDBMS design wisdom would put a huge red flag on anything that dynamically alters the table structure. Relational databases are more than flexible enough to handle pretty much any situation without requiring such measures.
My suggestion as for the structure would be to create a single Languages table to store the available languages, and then a Phrases table to store all the available phrases. Then use a Translations table to provide the actual translations of those phrases into the available languages. Something that might look like this:
Language
+----+---------+
| id | name |
+----+---------+
| 1 | English |
| 2 | Chinese |
+----+---------+
Phrase
+----+-------------+
| id | label |
+----+-------------+
| 1 | header |
| 2 | description |
+----+-------------+
Translations
+-------------+-----------+-----------------+
| language_id | phrase_id | translation |
+-------------+-----------+-----------------+
| 1 | 1 | Header |
| 1 | 2 | Description |
| 2 | 1 | 头 |
| 2 | 2 | 描述 |
+-------------+-----------+-----------------+
For small to medium sized databases, there should be no performance issues at all even using the default database configurations. If you get to huge sizes (where you are counting the database size in terabytes) you can optimize the database in many ways to keep the performance level acceptable.

Database relationship between two databases

I want to create a little blog system. Under each article should be a comment function. I think, I need 2 Databases (1x for the normal articles, 1x for the comments of ech article). Now I dont now how i can create a relationship between boths databases. Here is a picture:
On this picture are the attributes of each database. And how can i contact the databases then? (write & read)
make for every type you want a table. i.e one for articles, writers, categorys etc.
Table articles
+----+-----------+-------+------------+---------+-------------+
| id | writer_id | title | date | message | category_id |
+----+-----------+-------+------------+---------+-------------+
| 1 | 12 | foo | 2015-01-26 | text | 34 |
| 2 | 12 | bar | 2015-01-27 | bar | 32 |
+----+-----------+-------+------------+---------+-------------+
table writer and so on
+-----------+------+
| writer_id | name |
+-----------+------+
| 12 | test |
+-----------+------+
Table comments
+------------+------------+---------+------+
| comment_id | article_id | comment | date |
+------------+------------+---------+------+
and so on
afterwards you can connect them in your sql
SELECT
`articles`.`title`,
`writer`.`name`,
`comments`.`comment`
FROM
`articles`
LEFT JOIN `writer` ON (`writer`.`writer_id` = `articles`.`writer_id`)
LEFT JOIN `comments` ON (`comments`.`article_id` = `articles`.`id`)
Have a look at http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins for a visual explanation of joins.
You need two tables in the same database and you can connect them with a foreign key.
ARTICLE (ID_ARTICLE,WRITER,TITLE,DATE,MESSAGE....)
COMMENT (ID_COMMENT,FK_ARTICLE(to know the article), COMMENT_WRITER ... )

Database design with undetermined data

Recently I have been planning a system that allows a user to customize and add to a web interface. The app could be compared to a quiz creating system. The problem I'm having is how to design a schema that will allow for "variable" numbers of additions to be made to the application.
The first option that I looked into was just creating an object for the additions and then serializing it and putting it in its own column. The content wouldn't be edited often so writing would be minimal, reads however would be very often. (caching could be used to cut down)
The other option was using something other than mysql or postgresql such as cassandra. I've never used other databases before but would be interested in learning how to use them if they would improve the design of the system.
Any input on the subject would be appreciated.
Thank you.
*edit 29/3/14
Some information on the data being changed. For my idea above of using a serialized object, you could say that in the table I would store the name of the quiz, the number of points the quiz is worth and then a column called quiz data that would store the serialized object containing the information on the questions. So overall the object could look like this:
Questions(Array):{
[1](Object):Question{
Field-type(int):1
Field-title(string):"Whats your gender?"
Options(Array):{"Female", "Male"}
}
[2](Object):Question{
Field-type(int):2
Field-title(string):"Whats your name?"
}
}
The structure could vary of course but generally i would be storing integers to determin the type of field in the quiz and then a field to hold the label for the field and the options (if there are any) for that field.
In this scenario I would advise looking at MongoDB.
However if you want to work with MySQL you can think about the entity-attribute-value model in your design. The EAV model allows you to design for entries that contain a variable number of attributes.
edit
Following your update on the datatypes you would like to store, you could map your design as follows:
+-------------------------------------+
| QuizQuestions |
+----+---------+----------------------+
| id | type_id | question_txt |
+----+---------+----------------------+
| 1 | 1 | What's your gender? |
| 2 | 2 | What's your name? |
+----+---------+----------------------+
+-----------------------------------+
| QuestionTypes |
+----+--------------+---------------+
| id | attribute_id | description |
+----+--------------+---------------+
| 1 | 1 | Single select |
| 2 | 2 | Free text |
+----+--------------+---------------+
+----------------------------+
| QuestionValues |
+----+--------------+--------+
| id | question_id | value |
+----+--------------+--------+
| 1 | 1 | Male |
| 2 | 1 | Female |
+----+--------------+--------+
+-------------------------------+
| QuestionResponses |
+----+--------------+-----------+
| id | question_id | response |
+----+--------------+-----------+
| 1 | 1 | 1 |
| 2 | 2 | Fred |
+----+--------------+-----------+
This would then allow you to dynamically add various different questions (QuizQuestions), of different types (QuestionTypes), and then restrict them with different options (QuestionValues) and store those responses (QuestionResponses).

Grabbing individual elements in MySQL Table

I'm attempting to add Breadcrumbs to my website using a MySQL table, and I'm having difficulty at the moment.
I have a table named 'includes' created that stores information about the category, page, subpage, the title, and the ref (url) of the page. Category, Page, and Subpage are all php parameters passed from the page the user is on
My table is laid out like this:
|----------------------------------------------------------------|
| ID | Category | Page | Subpage | Title | Ref |
|----------------------------------------------------------------|
| 0 | | | | Home | ... |
| 1 | Software | | | Software | ... |
| 2 | Software | Desktop | | Desktop Software | ... |
| 3 | Software | Mobile | | Mobile Software | ... |
| 4 | Software | Desktop | Blah | Blah Blah | ... |
| ...
|----------------------------------------------------------------|
What I'm trying to do is make a query that will return only the required steps back to home for the breadcrumbs.
In other words, if the user is on "example.com/software/desktop/blah", the query will return rows 0,1,2, and 4. Or if I was on /software/mobile, it would only return rows 0,1, and 3.
My current attempts have been things like the following:
SELECT * FROM `includes` WHERE
`category` IS NULL AND `page` IS NULL AND `subpage` IS NULL OR
`category`='$category' AND `page` IS NULL AND `subpage` IS NULL OR
`category`='$category' AND `page`='$page' AND `subpage` IS NULL OR
`category`='$category' AND `page`='$page' AND `subpage`='$subpage'
Which not only don't work, but also seem more complex than it should have to be.
I'm probably overcomplicating this, or possibly just doing an entirely wrong method, which is why I've turned here.
Does anyone have a possible solution to this? Should I be looking at a more complex query? (admittedly, SQL is not my forte) Or should I be looking at a new SQL table, or possibly an entirely different method?
What you have is a hierarchical structure. The data is set up with parent-child relationships. There is a good description on how to work with hierarchical data here: http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/
You can make a self relation table like this
id | parent_it | title | Ref
1 | 0 | Home | ...
2 | 1 | Software | ...
3 | 2 | Desktop | ...
4 | 2 | Mobile | ...
5 | 3 | Blah | ...
So your query should get the last element
SELECT * FROM includes WHERE
tilte = 'Blah'
And then get the parent ID title and so on , like this the table structure will be better from my point of view & experience
OR
Generate your query based on the values you get , with simple loop count the arguments and based on that generate the query string then execute it
I hope this can help :)

Categories