Hypothetically, let's say I had multiple installations of some odd MySQL/PHP driven software. They are the same software so the database table structure is the same cross all of the installs. What I want to do, is make the software use a different database prefix for just one table. Specifically, a user table. So say the installs are set up like this:
Main install: /home/www/main, database main, prefix is1
Second install: /home/www/second, database main, prefix is2
Third install: /home/www/third, database main, prefix is3
So what I want is to tell second install and third install to pull from the users table on prefix is1 for its own data via that table. Thus, any user that registers on main install is also registered on second and third and vice versa. Is it possible, and how would I do it if it is? Even if it's just a workaround that gives the same basic result I would be happy.
If you don't want to modify the app's PHP source-code, and it's not already configurable in this respect, then another option is to modify the database, changing is2users and is3users to be views on is1users:
DROP TABLE is2users;
CREATE VIEW is2users AS SELECT * FROM is1users;
DROP TABLE is3users;
CREATE VIEW is3users AS SELECT * FROM is1users;
(See http://dev.mysql.com/doc/refman/5.0/en/views.html for general information on views, http://dev.mysql.com/doc/refman/5.0/en/create-view.html for information on CREATE VIEW specifically.)
Depending on the app, this may not work perfectly -- for example, the app might cache some information in memory (such as the current value of an identifier-sequence) -- but it will probably work. Test it before putting it in production!
Your php code likely goes something like this in something like cfg.php:
$prefix = 'is3'
and in something like user.model.php:
$sql = 'SELECT * FROM `'.$prefix.'users`';
So you need to change in two of three installs code for working with 'users' table. But it seems to be too dangerous.
The setup of this is easy, schema-wise. You mention 'installs' which means you are using some packaged library which probably contains a config file where you can change various settings, and chances are one of the settings is the table prefix. If there is no table prefix option you can browse the install code and find where the schema is located and change the prefix manually for each install.
Now comes the hardpart, getting the code to behave as you described. You will have to make your app aware of all three databases, meaning you will probably have to add two new database connectors to the code (one connector for each database). Then you will have to add logic to handle user CRUD functionality to insert/update/delete user data across all three databases (transaction would be good here).
What you are describing is possible, but will require some custom code.
Related
I'm new to Codeigniter and am just learning about the ion auth authentication system. I just have a few questions about it:
1) Is it possible to modify the default users table? (and would you advise for or against it?) I understand that there may be functions in the model, view, library or controller that expect the tables to have their exact default structures but for example, i have no need for a company column, so how can i go about removing it?
2) How can i add additional user information to the default users table? (Will it affect any functions if i just execute some sql to add columns to the default users table?)
3) This is kind of a follow on from theast question, would anyone recommend just creating a separate table for my additional user information and using their user id as the primary key in this new table and then just accessing tjat information via my own models?
Thanks for all your help!
Yes, it's possible to edit the users table, you will, however, have to go through the ion_auth_model / library to check for calls/writes to the field you are deleting. Otherwise you'll experience 500 errors for trying to insert data to a non-existent field.
Yes, you can add additional fields in phpmyadmin where you have access to the database itself. The additional fields will either need to be set to null (to prevent errors on writing if the data isn't present), OR you'll have to include those fields as required and add them to ion_auth's existing functions.
Solid idea, usually the rule I go by is keeping as little null fields as possible in the database. So if every user will have additional information, and you aren't expanding your table to a ridiculous length, then I'd append it to the users table. Otherwise, if you are adding optional additional fields, it's probably better to do an associative table.
Don't forget that you're the developer, libraries are used for convienice and security, but don't feel like you can't tailor them to better suit your needs. That's how we get cookie cutter applications.
Adding/removing fields to the default users table in the database is okay as long as you remove the associated code in Ion Library that depends on it. I encourage you to fork the Ion Authentication library and modify it as it fits your requirements.
If you want to leave the Ion Library unmodified, creating another table to store additional information is the right approach.
For modifying database tables/fields, using CodeIgniter's migration is recommended so that you can keep track of database changes inside a source code repository such as Git.
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
I'm creating Joomla3 component and I need to create some dummy content during the installation, I know that I can use sql file to fill the tables, but this works mainly for custom created tables specific for my component. Problem arises when I want to add something to the #__content table, the 'alias' column isn't considered as unique and there can occur duplicate entries, if someone tries to install the component several times.
I would like to know what is the best way to insert a record into #__content table without worrying about collateral damage like duplicate entries.
Thanks all !
Solution 1 :
You can use INSERT IGNORE so that while installing extension multiple times there will be no concern of duplicate entries.
Solution 2 :
In Joomla there is a provision of script file which a component can have.
So, when an extension is installed/update/uninstall joomla triggers or calls certain predefined function like install, update, preflight, postflight etc available in the extension script file.
You can add install method in your extension script and execute this sql file on this method so that this will not be called on extension update case
Solution 3 :
You can maintain a separate table in your database for this task and when you perform this dummy content creation you can mark this in your DB and further you can check whether this step has already done or not before initiating dummy content creation so that when someone install this extension multiple times this checking will prevent the same task to execute again and again.
I'm developing an application using CakePHP (latest version) framework for PHP that will unite several instalations of a CMS with a single registration form. I'm using a MySql DB. The problem is that I cannot modify the CMS code, I can only modify the DB data since very frequent CMS updates will overwrite my modifications.
The idea is that the system will keep a master Users table as shown in the diagram with the shared data. The table model of the master Users table and the child Users table is the same, except for a few CMS installation specific columns (as shown in the simplified diagram).
Now I'm trying to figure out a way to reflect the changes I do on master (INSERT and UPDATE) to occur on all of the child DBs. So when I make a change in my CakePHP app I want those fields that are shared to be updated in all child DB instances.
One solution would be to write manual MySQL queries for every single action in the application but that seems redundant and annoying.
How could I make my app to repeat all of the queries I do on my MASTER on every CHILD. Basicly if I UPDATE the name of entry ID 5 in MASTER, that that same query is ran on all of the child databases (which will hold the same entry under the same ID but with a few additional columns).
You could do that easily with CakePHP's model triggers (beforeSave, afterSave...) BUT keeping all that stuff synchronized will soon become your worst nightmare. Instead, I would do something like this:
Master.User has (id, name, password, specData1, specData2...)
Child1.User is a mysql VIEW: CREATE VIEW User AS SELECT id AS id, name AS name.., specData1 AS specData FROM Master.User
Yes, you can create cross-DB views. For the CMSs Child1.User is a table, all operations CREATE/DELETE/UPDATE are transparently done by the CMS on the VIEW thinking its a table. (but Master.User gets updated)
I am building an application using the latest copy of Codeigniter 2.0. My application is dynamic and is kind of like a custom CMS I guess you could say. I have a database table called 'settings' with the following fields:
id
name
value
Basically what I am currently doing is using a helper function to retrieve specific settings from my settings table like the site name or current theme. However I've started thinking that maybe the constant amount of database calls for retrieving settings is a bit too much on the database.
Is there a way of retrieving settings for my application from the database and then appending them to my configuration file? I've noticed Mojomotor does something similar and it is a CI 2.0 application, however I would much rather the simplest and easiest code to do so.
I would preferably like to be able to check every so often if a setting in the database has changed and update the configuration file. The less strain on the database the better.
The best solution lies in the middle. Not zero DB calls; and not one DB call per setting. Do one DB call per page load instead, and get every setting in a recordset / object that the rest of your app can refer to as needed.