Proper way to save multiple checkboxes to MySQL (Laravel 5.3) - php

Using Laravel 5.3 and MySQL 5.7.19.
I want to save bunch of options (true/false) to my User model.
These will be used to determine whether certain notifications will be sent to user or not. I will never need to filter Users by these flags. There is a possibility that new flags will be introduced but I don't think the number of flags should ever go above 20-50.
1. My first idea is to save each of the options as separate tinyint(1) column but it will look really, really ugly, even if I prefix these with something like notification_flags_.
2. Second idea is to save the values as integer column and use bitwise operations to deduce the property using PHP. This will take slightly more time to implement but it will look cleaner. Not sure about the performance but probably slower than method 1.
3. Third option is to use another table for flags (let's call this NotficationFlag model) and connect each User to this table via pivot table (using Laravel's manyToMany helper/method (not sure of the proper name)). This option would give me most flexibility (which I don't really need given the nature of the problem) and I think it would be the slowest, but I don't really know.
4. Fourth option would be to have oneToOne relation with NotificationFlag model and in this model to have a column for each flag. This seems to me as the same as option one but a bit nicer, and a bit slower.
What is the best way to do this? It seems to me that first option is the best but something inside me is telling me there must be a nicer way. Is there?

Related

How do you dynamically insert parameters into a mySQL database with php?

I try to insert data into a mySQL table and i don't know yet how many parameters there will be.
So i need to find out a way how to insert parameters dynamically.
You can do it that way:
Insert into mytable (parameters) VALUES ('Ford;red;100kW;diesel;');
Insert into mytable (parameters) VALUES ('Ford;red;100kW;electric;40kWH');
So if you have to add a electric car, you need the kWH, which you didn't need for the petrol car.
Or you do it that way:
Insert into mytable(name, color, kW, engine) VALUES ('Ford', 'red', '100', 'diesel')
ALTER TABLE mytable ADD kWh VARCHAR( 255 ) after engine
Insert into mytable(name, color, kW, engine, kWh) VALUES ('Ford', 'red', '100', 'electric', '40')
In first case you have to hande all the data with string operations like explode, in second case you have to allow the user to add columns with php.
What is the better way? Or is there another way that is even better?
I don't see any similarity with the other question.
This is a verry dificult question. I hope i understood it correctly.
Disclaimer
This is a long post, it may contain errors. Feel free to correct those or ask for clarifiation. It also is (because of the nature of the question) somewhat oppinion based. I tried to balance all possibilities.
I assumed a object orriented approach to this, i.e. that object should be stored.
TL;DR: It might be best to not do this programmatically.
Evaluation
The first answer has the advantage, that you may split the text at runtime and dynamically create a new Object, which will not lead to a PDOException (or whatever you are using). This however also has it's disadvantages. It can lead to you using reflections a lot. Why? If you want to alter the Table at runtime, i have to asume you do not know what kind of Objects are to be expected. This leads to you creating those objects "on the fly". This would also suggest, that you should store the Objects name somehow.
The seconds answer raises a Question. How do you read from that Database?
If you dynamically read of that database (i.e. programmatically defining which columns you are going to need): How do you know, which columns to read from? What ensures you, that the columns will exist? You would have to check that the column you request exists. This may get messy real fast, because you would have to check for each column. And if it does exist, but is not set, what will be the default value for it?
If you statically read of that database: Why not design the database beforehand to hold the kWh column? It might be null at some point, but you could compensate for that, by ignoring them.
If you know the Object you want to use beforehand, design your Database to be able to hold it.
Another way to aproach this
Or is there another way that is even better?
You may be happy to use Relational Databases and abstruct those with a Data Access Object. Even tho this answer dipps deep into design aspects, you may go best with designing your application first. Go ahead an create a EER-Diagram, that represents your data-structure. You can have a generic car entity, that is extended by the patrol car and the electric car (and even a fusion car). There are plenty of tools out there, that help you create such a diagram and convert it into an DDL for the database of your choice.
Conclusion
To be concrete, if you realy have to alter the table at runtime, i would recommend going with the second approach and add a default value to it. However, based on the question you asked, i can't realy see you getting far with it. It would mean that you would have an unkown Object that you want to store.
If that is the case, why not create a new Table with the objects name, that holds the fields of the object as columns? That would allow you to have an acces like this (asuming a repository that stores said object):
$object = new TestObject();
repository->store($object);
Upon calling repository->store(), the repository will check if the database has a table called "TestObject" and, if not, create it. If the table was created, it than could proceed to alter it and add the columns. So, the following would use this:
$object = $repository->load("TestObject");
The Repository would now check for the column TestObject and may create a new TestObject at runtime like this:
function load($name) {
$returnValue = new $name;
// Set the fields based on the database entries.
}
It has the big advantage, that you would only have to check, whether or not the table exists and (if yes) create a new Object or (if not) throw an Exception.
Ofcourse this comes with more problems. Error handling is not done here (for example, what happens with namespaces and what happens, if there are more objects with the same name), to keep it simple. But this should bring the point accross.
Sorry for the long post, have a nice day :)

Mongodb Multiple Updates with PHP

I'm new to Mongodb (using PHP) and being that I'm used to RDMS I have what maybe a newbie question. I have a collection of "pages" that have a field called "tags" in which I have a series of tags, "happy, sad, angry, irtated".
Now I have another collection, called... let's say "users" and I want the user to be able to specify which tags are important to them... so this collection also has a field called "tags" in which I would have maybe, "Happy, and irtated"
Now... here comes the question, let's say I wanted to correct the spelling of irtated in both collections. Normally the RDMS world, I would have referenced these to a single table and then done an innerjoin such that changing the value in one spot would cascade everywhere... Or let say I wanted to remove a tag from the system... say, I didn't want Happy to be used anymore and I wanted to just remove it from all my collections where it exists...
Thoughts?
Why are you using Mongodb instead of RDBMS? most probably you want higher speed. Since in mongodb most related data in one place (in storage devices) so it is easy to retrieve data.That's why we keep same data in different places (Data redundancy). But when it comes to your case you need to keep more time to do the programming to do the same over RDBMS. So both RDBMS and NOSQL have their won pros and cons, and you will never have both profit from one account(Mongodb).

What are useful architectures for storing user settings?

I want to store some user settings and I thought of 3 options, since it's my first project and I want to start it the right way, I can't figure out which is the the optimal way of doing this..
Storing single settings directly in columns in the user table
Having a user_settings table with the columns setting_name, setting_value and user_id
Storing a JSON string in the user table, in a column named something like "user_settings_json"
On a design analysis, I noticed wordpress stores it in a separate table, but I'm not sure that's necessary for every application (since mine does not have nearly as many user settings as wp does)
I'm using Laravel, PHP, javascript/jquery.
Which do you guys think would be, most useful, overall better, in terms of design, serviceability and performance?
Storing a JSON string ? NO !
You want to be able to isolate the settings, just query what you need. Therefore, keep it in separate columns!
As for the question if you have to make a separate table, no, you don't have to. When you just got some simple settings you can just add the columns to the existing table of users. Be aware of the limitations here. If you do need advanced settings, i would recommend using a separate table. Better do it too early. Not every setting might apply to every user. For example when you've got premium accounts who can have more settings. So, keeping it separate is what I would do.
Btw, I wouldn't let the columns start with 'setting_' if they are already in a separate table containing 'setting' in the name.
Conclusion: Option 2 :)
Recently I've made package for my project which uses Laravel 9 and it allows you to add settings to any Laravel model. It can cast values to primitive types like bool, int, but also to custom classes. Eg.:
$user->settings->get('is_gamer');
$user->settings->set('games_count', 10);
// or global site scoped
Settings::get('display_annoucement');
// more advanced usage with definition of custom class
$address = $user->settings->get('address');
$address->country = 'Poland';
$address->zip = '11-222';
$address->city = 'Warsaw';
$user->settings->put('address', $address);
// any model that implements trait
$article->settings->get('show_breadcrumbs');
$post->settings->get('allow_replies');
You can find it here: https://github.com/npabisz/laravel-settings

Detecting field changes - cakePHP

What I want
I want to see which fields on a table was changed and save that name into the database under the edit column.
What I have
Currently, not much. Just the standard cakePHP baked edit view and controller. I have done it previously, but not with cakePHP. What I did was retrieve the record, and if it's different to what the user entered, save the name of the column that was edited in the edit column corresponding to the row.
My Question
Could someone tell me how I would compare user input with what is on the database?
Behaviors like the "Logable" Behavior already do that and store the information separately.
I advice you to do the same. the "changes" do not necessarily need to be put into the same table. If you feel they do, though, you could make your own "modified" Logable behavior that only creates the "diff" and stores it into a field of your choice on the same record.
PS: You might also want to take a look at the RevisionBehavior.
It also contains some diff algorithm.
Then there is the WhoDidIt behavior which stores the user that last modified the record. In the same table, though. So this combined with the above should do the trick.
Either way:
use callbacks (beforeSave/afterSave) on model itself or (cleaner) as behavior
calculate diff
store the diff in a separate table or as in your case in an extra table field.
Actually writing something up here that does the job is pretty straight-forward.
The voluntary exercise here would be to write it more "generic". Maybe you want to reuse the same functionality again for other models in the future? Copy-and-paste would be pretty bad style then. The goal here would be to create some generic piece of code you can easily reuse. If your initial code works, try to rewrite it into a generic ChangesBehavior that you can attach to as many models you like. You can take the linked examples or take a look at other behaviors out there to get an idea how to do that.
Also you can publish your behavior in github/plugins.cakephp and give the community something back again. Maybe others find it useful, too.

How do I create an empty table with SQL?

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!

Categories