How to dynamically load code in php + database - php

For some time now I'm thinking about a nice way on how to dynamically load code in php based on database entries. I've tried to look up something related, but couldn't really find anything that answered my question(s) thoroughly. I'm using Laravel - not sure if this might be a subject to solve this particular problem.
See the following code for "example data" where I tried to give a quick overview over the database structure. So for a game, lets say we have characters that can be at a location. Any location basically looks the same. You have a form to write a message at this location - nothing fancy. But then there might be some exceptions. For example you might have a location, that implements some more logic such as listing all online characters (+ showing their current location's name.). Or a location might show some other additional content.
This is what I came up with so far, but neither seems optimal:
Creating different tables for different types of locations (this seems very bad to me actually).
Create another table, f.e. modules, and have a many-to-many relationship with the location table. the modules table would then have entries for a location that tell the application what to "execute". F.e., a location might have the entries thread, for allowing to post messages, list, for showing an overview of online characters and their locations, trader, to allow some gameplay mechanics etc.
To me the second option seems to be kind of the right way of achieving what I want to achieve. I would have classes, functions etc. that would represent these modules. But it too seems very hardcode-y. Meaning, that for one in the code behind I would have to distinct between the values which I might or might not want to change in the future, which then would require a lot of refactoring. Because I have to distinct between strings, this design is prone to typos and what not...
character:
id | location_id (nullable) | name
---------------------------------
1 | 1 | Test
location:
id | name
----------------
1 | Location #1
2 | Online Characters
For the above presented version I would add:
modules:
id | name
---------
1 | thread
2 | list
3 | trader
location_modules:
location_id | modules_id
------------------------
1 | 1
1 | 3
2 | 2

Related

Best MySQL Database Structure for a Yellow Pages Site

Im building a yellow pages site. I tried multiple database structures. Im not sure which one is best. Here are few I considered,
Saving all business data - name, phone, email etc in one table, list of tags in another, and mapping data id and tag id for tag-data relationship in a third table. I found this cumbersome since I'll be doing most things directly in the database (at least initially, before launch) and hence distributing everything can be problematic in my case. This one is a clean solution I must admit though.
Saving biz entries in one table with a separate column for tags (that'll contain comma separated(or JSON) tags for every entry). Then retrieving results using like query or full-text search for a tag. This one will be slower and will get more slow as db size increases. Also its not easy to maintain - suppose if I have to rename a tag.
(My Preferred Choice) Distributing biz data in different tables based on type - all banks in one, hotels, restaurants etc in separate tables. A separate table for all tags containing a rule for searching data from the table. Here is a detailed explanation.
Biz Tables:
college_tbl, bank_tbl, hotel_tbl, restaurant_tbl...so on
Tags Table
ID | Biz Table | Tag Name | Tag Key | Match Rule (col:like_query_part)
1 | bank_tbl | Citi Bank Branches | ['citi','bank'] | 'name:%$1%$2%'
2 | restaurant_tbl | Pizza Hut Restaurants | ['pizza','hut'] | 'name:%$1%$2%'
3 | hotel_tbl | The Leela Hotels | ['the leela'] | 'name:%$1%'
I'll then use 'Match rule' in like query to fetch results from 'Biz Table' for 'Tag Name'.
Im going forward with the third approach. I feel its simple, reduces the need of third data-tag relationship table, renaming is easy and performance won't get down if table has limited entries - say 1 million max per table.
Im scratching my head for the last 15 days to find the best structure and feel this one is pretty good in my case.
Please suggest a better approach or if this approach could have some issues later on.
Use Number 1. Period, full stop.
The mistake is "doing things directly in the database" rather than developing the API first.
Number 2 has one advantage -- FULLTEXT search. That can be tacked onto #1 after you have have a working API and some data to play with.
Number 3 (multiple similar tables) is a fisaco. Numerous Q&A ask about such; the reply is always "NO".

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)

Filter tags by tags and count

My mysql structure is as follows:
+----+-------------------------+-------------+-----------+--------------+
| id | title/text/moretext/img | language_id | course_id | country_code |
+----+-------------------------+-------------+-----------+--------------+
| 1 | Plenty of information | 1 | 3 | it |
+----+-------------------------+-------------+-----------+--------------+
I'm using the laravel framework to build my site.
This is a recipe. It is an appetiser (course_id 3 translates to appetiser using php arrays since page is multilingual).
This appetiser is from it. 'it' translates to Italy, again in PHP since the country names will be multilingual.
The recipe is written in English (language_id is a one to many relationship to a languages table, language id 1 is English).
This information is given in case it changes anything, which I doubt, but it's better to play it safe.
Each article will have only one of each of these tags.
What I need is a select list echoing all available options (options relating to filters in use, so if I have no recipes from South-Africa in French, South-Africa won't show in the filter list if French is the selected language).
Google yielded nothing, and I'm running out of time and my ideas are at zero. Is there any way to implement this with ease?
I've looked into http://luis-almeida.github.com/filtrify/ and think it would be exactly what I want in functionality, but I think it would be way too heavy on a large database as I'd have to query the entire database and make a list out of that. But I might be wrong.
An implementation using something like http://harvesthq.github.com/chosen/ would also be possible for selections, but I don't know how to even implement it for this.
Any help would be truly fantastic. I'm way over my head here and am all out of programming passion. I've spent a couple of days on this already and am drawing a blank. None else to ask.
A quick and dirty way to get past this (you can always come back and enhance it later) would be
SELECT DISTINCT country_code, language_id
FROM recipes
ORDER BY country_code, language_id
with whatever joins/translations are necessary to get country names and language names, then make a single dropdown from the result...
Deutschland - Deutsch
France - Francais
South Africa - Afrikaans
South Africa - English
United States - English
So each item is both the country name and the language. If most countries have only one or two languages spoken, this shouldn't be overwhelming to the user.

Handling 300 field form in the database

So, I'm dealing with an enormous online form right now. It's separated into different sections visually, but those tend to change. With around 300 fields, it almost seems ridiculous to put them into a single table, though if I separate them and someone decides to move a field to a different section on the front end on several different occasions, it will become a mess in the database and fields won't match their front end sections.
I'm essentially asking: What is the best way to organize something like this in a normalized fashion?
You could move the field names to another table and reference them in the value table.
Example
field_id | field_name
------------------------
1 | first_name
2 | last_name
Then reference from the values:
value_id | field_id | value
--------------------------------
1 | 1 | John
2 | 2 | Doe
3 | 1 | Max
4 | 2 | Jefferson
If you're going to use a SQL database, then the Entity-Attribute-Value model (EAV) described above is probably a good answer. You might also want to mix in a couple of denormalized tables with common or specialized data.
Another option might be a document store though; this sounds like just the kind of problem that inspired data stores like MongoDB. In MongoDB you just store everything as a giant json document. If some data isn't needed for some records and is left out, it isn't considered "bad" in the way sparsely populated wide SQL database tables are.
You can group your fields. Separate them as components and you will probably notice, that you can make multiple tables out off that one. Also by separating table you cant make form with, for example:
fieldset tags
separate it in multiple steps (it think the best solution)
multiple ajax requests for each form after previous is filled
form separated by open/close javascript windows
Database design, object design, and form design are three very different elements. If there are relationships between the data in a one to may fashion, you should have different tables to normalize the data. If however, everything is a One-to-one relationship then having all 300 in the same table is perfectly acceptable. I find it difficult to believe that there is a logical or even physical construct that has 300 elements unto itself; but it's possible. If you start getting into attribute data of something lets say we're talking about a vehicle. We could be talking about a car, a truck, a semi, a motorcycle, a bicycle, etc... each of those types of vehicles have different properties which would be managed in separate tables to normalize the data. moving elements of them to different pages wouldn't make a whole lot of sense; but moving common attributes might. For example I wouldn't ask about color on section 1 and again in section 4. But I might section things out to describe make, model, and then custom attributes.

Separating MySQL content via PHP on a "per-country/user preference" basis

Okay, I'll lay this out simply:
I have one database that has content in it but I need to set up a conditon where if the user has selected Britain instead of the U.S. or vice versa -- some content will not show. This condition can be applied via a checkbox in the backend like so.
"Hello, I'm a paragraph" show in [x] Britian [x] U.S.
I'm not looking into actual IP Addresses or anything of that sort as the site will simply redirect to root/uk or root/us subfolders upon the user's selection on the index page. What kind of a unique parameter would I have incorporate in the db or php?
Thank You!
Add a column in the database display_content, make it a EMUN and set the values to 'britain','usa','all' then make the adjustments in your code to check for Britain/USA. you can either choose to display all, Britain or USA.
That's an interesting problem. Because although it's language oriented, it's not actually I18N related - you're talking about deny access to content based on a language preference, not displaying localized content.
Here's one idea: use a permission model
Create two permissions such as "read-enUS-content" and "read-enGB-content"
Based on the user's selection, grant them the correct permission for the length of their session (which you can persist if you wish via cookies or user prefs)
It would then be the responsibility of the application to allow/deny the content based on their permissions.
Then the question becomes, how do you connect content to permissions? There are a multitude of ways, but one approach is a bitmask column.
00
||
|+--- Read enUS bit
+---- Read enGB bit
Which might look like this when implemented
Articles
+----+---------+-----------------+
| id | content | read_perm_level |
+----+---------+-----------------+
| 1 | foo | 1 |
| 2 | bar | 2 |
| 3 | baz | 3 |
+----+---------+-----------------+
This means that 'foo' is only readable by enUS, 'bar' is only readable by enGB, and 'baz' is readable by all.
But you could also do a full permission's table and connect the content to it that way.
The most straightforward model for this would be an associative table in your database. You'd thus have:
paragraphs (paragraph_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, paragraph_text TEXT, ...) ENGINE=InnoDB;
paragraph_countries (paragraph_id INT UNSIGNED, country_code CHAR(2)) ENGINE=Innodb;
When saving the paragraph settings, perform these steps:
BEGIN WORK (to start a transaction)
DELETE FROM paragraph_countries WHERE paragraph_id = ...
(foreach checked country): INSERT INTO paragraph_countries (...)
COMMIT (to commit the transaction)
To select paragraphs relevant to the current country, simply JOIN to the associated table with the appropriate country code.

Categories