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
Related
I'm pretty new to Laravel, so I'm struggling with the logic for what is essentially a CMS with multiple content types.
Say I have 3 content types; Food, Books and Cars. Every item in all content types has a name, URL and a couple of other fields.
I can create, update and delete any of these resources with most likely the same code replicated 3 times. The only difference would be with a create or update as the field names would differ between them.
Should I just duplicate these fields/functions for each controller, or create some common ground in one place?
The crossover of fields/functions initially will not be huge, however, it seems inefficient let's say if I had 10 content types and I want to add one field to all of them I have to update code in a large number of places.
If I had a central "Node" that contained the id's and common fields for ALL items in every content type, then have this linked to individual tables for the custom fields, I'm in a much better position when I want to add, update or delete common fields.
I've currently got 3 controllers and have only worked on one so far so I have an index(), show() and edit() function in the controller.
As a test, I created a Node model with php artisan make:model Node -mcr and simply extended the existing Controllers so they were extending NodeController. Which just threw up an error like this;
Declaration of App\Http\Controllers\FoodController::show(App\Food$food) should be compatible with App\Http\Controllers\NodeController::show(App\Node $node)
This is likely not the way to go about it anyway, but I simply do not know the recommended practice for this.
Most appropriate and standard best practice for your problem is,
have a single database table, let's say table name as node, which will contain all the common fields, and have another table as categories and relate it with node table (1-m) to categorize type of node such as car,book,food etc., and make one more table, let's say node_meta which will store all additional attributes depending on the type of node,
(you may have a look on the wordpress CMS database ER Diagram which has similar db design.)
Polymorphic relation is not a good idea for this as stated by another user above, it has some limitation when it comes to querying underlying data, for example you cannot apply whereHas query and still there is no official solution to this problem.
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).
I'm facing a migration problem on the job. Right now we have a single database which is used by our website and by a backoffice tool.
As part of trying to improve our code in the website, we've desgined a new schema for several tables in the database.
As an example let's take the products table. It's fairly standard with fields like description, name, product code, price, creation date etc. We now have a new table, let's call it better_products. The problem is, we can change the website code all we want, but we can't touch the backoffice tool's code which relies heavily on the old products table.
We're going to end up in a situation in production where the backoffice tool is writing to the old products table, and the website is reading from the new better_products table. The question is, how do we keep both of them in sync? I've been googling around for some time now, and by far the most common solution is to use triggers, and map the incoming data to the new table. I've written the AFTER INSERT trigger for the products, but when I went to write the UPDATE trigger it turned out there's no way to iterate over the fields that changed inside the trigger and map them over. This means writing out the fields by hand a la 'IF NEW.fieldName <> OLD.fieldName THEN' which is ugly and requires listing the fields out by hand.
Is there a better way? a semi-better way? anything except writing this out field by field?
Is there a better practice than using triggers?
Please don't suggest changing the backoffice tool as this is not a realistic option right now. It's planned, but not soon enough for us to be able to wait for it.
Create a view in the mysql database called better_products that is a select statement on the old product but with aliases for the column names that have changed.
Eventually, you can update the code in the backoffice app, to use this view. Once both systems are using the new view, that view can be replaced by an actual table called better_products that has all the data from the old table copied over.
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.
Let's say that I have a Post table and an Update table. What I would like to know is how could I modify the 'modified' time field in the Post table when an update is added to the update table. I have searched - but can't seem to figure it out.
I hope this makes sense...
Thanks!
Yes you can do so, for example you could do this in the model. Implement a afterSave() method in the Update table. There you can update the related Post.
http://book.cakephp.org/2.0/en/models/callback-methods.html
Other way around would be removing modified in the Post model and creating an afterFind() method in the model. In most instances you should not do this because of data load but might be useful when using lots of inserts and a very low amount of reads.
The most nice way is to put those methods into a Behaviour which creates a separation of concerns and also allows re-use:
http://book.cakephp.org/2.0/en/models/behaviors.html
Addition while thinking about it: You could of course update the Post.modified field but it would be more clear and better to create a separate field for it. So Post.latestcomment datetime field. Then also edits to the post will be registered as an update. Also it allows more flexible scheduling. Next to that you know whether there are any posts also.