Detecting field changes - cakePHP - php

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.

Related

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

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?

To what extent is duplicate code OK in a model with CodeIgniter?

This is a long running question that gets me every time I am developing.
I suppose it is not specific to CodeIgniter, but as I am using it, I will consider it in my example.
Firstly, which is better:
function add_entry($data_array)
{
//code to add entry
}
function edit_entry($data_array)
{
//code to update entry
}
OR
function save_changes($what,$data_array)
{
//if what == update update
//otherwise insert
}
Both produce the same action, but does it really matter which one you use?
Getting onto more complicated things.
I have a page where I need to get ONE entry from the database.
I also have a page where I need to get all the entries from the same database ordered by a user specified column.
My resultant method is a function similar to
function($data_array,$order_by='',$limit='')
{
//get where $data_array
//if order_by!='' add order by
//if limit !='' add limit
}
As I develop my application and realise new places where I need 'similar' database functionality I am what feels like hacking previous methods so they work with all my case scenarios. The methods end up containing lots of conditional statements, and getting quite complex with in some cases 4 or 5 input parameters.
Have I missed the point? I don't want duplicate code, and when for the most part the functions are very similar I feel like this 'hacking' methodology works best.
Could someone advise?
Finally my admin functionality is part of the same application in an admin controller. I have an admin model which contains specific methods for admin db interaction. I however use some model functionality from 'user' models.
FOr example if on an admin page I need to get details of a db entry I may load the user model to access this function. There is nothing wrong/insecure about this..? right?
In addition to that within my admin model itself I need to get data about a user database entry so I call my user model directly from my admin model. This is strictly OK, but why? If i need data and there is already a method in my user model which gets it.. it seems a little pointless to rewrite the code in the admin model BUT each time that function is called does it load the whole user model again?
Thanks a lot all.
In order, add edit in the model vs save. Personally I have a save built in MY_Model that chooses whether it is a save or an edit depending on the existence of a primary key in the data being passed, so obviously I prefer that method it means a lot less duplication of code since I can use the save for any table without having functions in the model at all.
As to the second question I think it depends on situation. I also have a number of functions that have a ton of conditionals on them depending on where they're used and for what. In some cases I'm finding this makes the legibility of the code a little rough. If you're running them all through if statements it also could be impacting performance. DRY is a concept, not a rule and like other design concepts there are times when they just don't make sense, it's like database normalization, it's my personal opinion it's VERY easy to over normalize a database and destroy performance and usability.
Finally, using user functions in the admin code. I don't see an issue here at all, the reverse probably isn't true, but rewriting a function just because it's an "admin" function, when it's identical to a user function is utterly pointless. So you're correct there, it's a waste of time and space.

cakephp update modified time on another table or model

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.

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!

MySQL Status Model -- Best Implementation?

So I'm working on a framework-esque system with one of my co-workers. Our current challenge is how to best implement statuses. Oftentimes, a status will carry with it unique data (a color for a table row, or text to be displayed to a user. etc). Currently, we have a statuses table which contains all this data. Contained in that table is a column: "css_class", which, whenever a record has that status, the specified CSS class is attached to the element (in this case a tr). Also, in order to assign another record a specific status, a foreign key is specified in that database table (in this case, a user has a specific status. So in the users table, there is a statuses_id foreign key). This implementation works alright, but there are a few problems. First, what if I need to perform a specific action in PHP if a record is in a specific status? The way we do it now is something like this:
if($user->status==0)
{
//execute some code
}
This really doesn't work well if statuses can change. Change one status, and the associated code either breaks or behaves differently than intended.
The other issue, and the main reason for posting a question is that the table contains the column "css_class". This is very versatile and allows us change the style of a specific status very quickly. But we really dislike the idea of putting code inside a database. Perhaps having CSS classes in a database isn't necessarily a bad thing, but I really don't know what the common practice is. Any ideas?
EDIT:
What I've gathered from the first few answers is that I should keep all my view stuff out of my model stuff in order to maintain an MVC framework. My argument is that if I keep the css_class name out of the database, then I'm checking the status id in the view in order to decide which class to assign it. So if I put the class in the database, I'm putting View information in the Model. If I don't put CSS classes in the database then I'm putting Model information in the View (checking which ID it belongs to). So by not muddying up the Model, I muddy up the view instead.......
The most elegant way I've seen this solved so far (and I've worked with a few MVC implementations now) is to store only the relevant data in the database. E.g. you'd store status="red" in the database, and leave it up to the view to know what to do with a red status, in terms of CSS. The problem is then solved by designing a sufficiently advanced View layer that creates reusable structures -- that way you don't need to always be updating things on a page-by-page basis when the css changes.
Passing this information up to the Model somewhat defeats the point of the content/presentation separation, because now your code needs to know to pull presentation information off the database and forward it along to the View level or, shudder, you'll be pulling that stuff from the database right in your View layer code, which makes maintenance a nightmare, as you've now lost control over the information flow.
If you want to continue your paradigm of storing this in the DB, you could make another table that maps VARCHAR names of the statuses to their corresponding INTEGER IDs.
However, if this was my framework. I would not be storing view information like this in the database. This would be handled by the V of my MVC setup.
From a data modelling point of view:
Have a different table for each "kind" of status; keep user statuses separate from page statuses (for example) - group the like entities together.
Don't put the CSS classes into the database, but use some form of status indicator - this could be an ENUM column, if you know the set of possible statuses up front. Transform this into the appropriate CSS class in the view layer. You don't want to end up in a situation where your CSS can't be changed because some data in the database prevents it.

Categories