How to remove obsolete database columns in SilverStripe - php

Is there a convenient way to remove obsolete table columns from the database? I'm wondering if there is a more convention-based solutions rather than logging into PHPMyADMIN and deleting columns manually.
Example
When installing SilverStripe-Fluent and adding an extra locale (eg nz-NZ) the module will split each SiteTree record to add extra translation columns with prefix _nz-NZ. Suppose we delete the extra locale (nz-NZ), the columns will stay there after a /dev/build.

there was a great module DBPlumber for version 2.4 that had this function but I'm guessing you are using a later version! It would be great if this was upgraded for V3.
The module artefact cleaner would be ideal. Its description from the github page is...
Find and optionally delete disused tables and fields in a SilverStripe
database.
During development of a SilverStripe application it is common to
delete a data object class or remove a field from a data object. This
leaves obsolete columns and tables in your database. Because these
columns or tables may contain data that you still want, the
SilverStripe framework doesn't delete those automatically. This task
displays the obsolete columns and tables in the form of SQL DROP and
ALTER commands. It also provides a way to delete them. If you do that,
there is no undo, so always make a backup first.

Related

Codeigniter Ion Auth editing users table

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.

Creating dummy content for Joomla3 component

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.

(Cake)PHP - Updating child databases with data from master

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)

Different table prefix for one table?

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.

Simple versioning (in PHP/Zend Framework)?

i am wondering how can i have simple versioning, say i want to be able to undo past edits (just up to 3 will do) to a post. maybe because the app allows other user to edit a post. but i may want the owner to restore the post for example.
do i just store the full post in another field?
One suggestion could be something like this:
you propably have each post as a separate row in the table and it has indexes that point to right threat and you retain their order by those indexes.
Add a "revision" to each post row. Everytime user edits the post, you store a new row into table but with higher revision. And when showing the posts, you just fetch the one with highest revision..
I've done this previously by creating a table which contains the following columns:
id, serialisation value of entire row you want backed up, the table it is for, datetime, why the backup was created.
That way you have a complete listing of all the versions of that table. I use Doctrine ORM so that way I can setup a postSave hook to create a new backup version in that table.
Doctrine Versionable Bebaviour may be the simplest solution for you:
Doctrine - Doctrine ORM for PHP - Versionable

Categories