i want to create a web page with data, this data can be edited in Real Time.
Users will see data in Real Time and can edit it, something like "Google Sheets" where everyone can edit the same file and see others changes in real time.
I will be using PHP, MYSQL, AngularJS.
I want to consult you on how to do it in the best way, this is some points that i thought of:
Use angular polling every X seconds to update page data in real time, but if user editing one of the fields, how can i prevent from this specific field to be updated by polling?
How can i LOCK specific field that user is editing, to prevent 2 users to edit the same field in real time
There is any better way to pull data in real time than angular polling?
When user editing text field i want to update it in database without "submit" or save button, i thought to save the data after 3 seconds, any better ideas?
Thank you,
1:
I'd suggest for you to have an array of objects or a datastructure similar to that, which contains the fields, in your AngularJS controller. When a user starts editing a certain field, you could set isEditing to true in the field object in your datastructure. Whenever an update comes in, you loop through your datastructure and only update fields of which isEditing isn't set / isn't true.
For making it more realtime, instead of polling, setup WebSockets and let the server broadcast the newest values of a field to all editors whenever it gets changed.
2:
For locking a field that a certain user is working on, you could add a locked column to the database table containing the fields. Whenever a user wants to start editing, the following would occur:
User requests to edit a field
Server checks if the field is locked
If the field isn't locked, the user is permitted to edit the field and the server sets the locked column to true or to the username, depending on your needs.
If the field is locked, the user isn't permitted to edit the field
When a user saves a field after editing it, you should set the locked column to false. You should probably also set the locked column to false whenever the editing user gets disconnected.
3:
PHP on it's own is not able to send data to the client without the client making a request. You'd need to add WebSocket support to PHP (for example http://socketo.me/, haven't tried that out though).
If you are interested in a server platform that is able to do this out of the box, you could take a look at http://nodejs.org. When you plan on using Node.js, I suggest using http://socket.io/ for maximum browser compatibility. (it includes fallbacks for whenever WebSockets aren't supported by the users browser)
4:
You could save the current value every x seconds if the value is different from the previous save. This would be more efficient than always saving the value. You'd need to save the previously saved value in a variable for this.
Related
I have a question, some might have encountered while working with data. Trying to figure out how to implement "signature" for data passed back and forth to SQL Server via PHP.
For example, I have a sales order that contains dates, numbers, other variables (string), etc.
The idea is that when that data is inserted into SQL, a "signature" is created based on all the variables (around 30-40) and stored in that table. That signature will be sent to the user when user pulls the data. Then, when a user updates that data and sends back to SQL along with the current signature, PHP would compare that current data signature with the one stored in the database and update the data if it matches. if not - the user will get a notification saying something like "the state of the order has been changed, new data available".
This will prevent one user from overwriting the data if that data has been changed by another user while the first user worked on it.
I thought to add "user signature" which is comparatively easy. However it does not resolve the situation when the same user has opened multiple windows with that data and then accidentally tries to submit updates from one window after he already submitted some data from another window. (Some users are old folks and not tech savvy and may have open multiple windows in the browser, you know).
Locking records won't work here as the data has to be accessible by multiple users at any time.
Thank you for your help!
NOTE: If someone is using SQL Server Management Studio, seems like you can add this column only via query. At least I coud not find this option in "design" view.
ALTER TABLE table_name ADD Version rowversion;
I have a laravel app that is being used by multiple users at once, they all have the possibility to edit some projects in our system.
What I dont want is to have 2 people at the same time editing the same form.
If that happens I would like to tell other users that the current form is locked and is being edited by username.
If user then leaves or submits the form, then the form is opened for other users to work with.
I have checked out both optimistic and pessimistic locking, I don't think this is correct for me
What I was thinking of doing, was to create a unique identifier in the table, that is being edited, and if the user on the page has the identifier, I would lock all other out, but how would I know if the user closes the browser window? then all other users still can't access the page/form?
How would you guys suggest I go about this?
Add a nullable locked_to column to your projects database. Then in the Project model add this field to $dates array so it can be converted to Carbon instances automatically.
When someone opens the project for edit just set locked_to field to future date, i think +5 seconds may be a good choice. Edit form should send ajax request every 5 seconds to keep project locked for next 5 seconds.
When user saves project changes, locking will be stopped cause no ajax requests will be send. In that case you also have field which may tell you when the project was opened for the last time.
User won't be able to edit project if locked_to field is equal or greater than new Carbon instance.
UPDATE - more info
There is no need to clear this field. If user didn't finish editing - he just reloaded page, navigated to other page, closed window or browser, died etc... ajax for locking won't be executed anymore, so in the next 5 second currently edited project will be unlocked - locked_to field will contain earlier date than current.
If the user keeps the page open put dead man switch prompt "are you still there", no user input will cause the page to stop the 5 second ajax refresh, thus allowing new users access.
If user returns the next day and clicks Yes, simply refresh the page, check if someone else doesn't already have it locked in and alert, alerting accordingly, but if not, restart the ajax 5 second timer.
How to lock a text field when one user typing in one text field??
Means that when 1 user typing in the text field, other user unable to type in that particular text field.. Is there a way to do that??
The way I understand it, you'll need to use JavaScript to constantly poll the server for changes. When a user starts typing, he'll Ajax the server notifying it of that. The server will save the new state to the database, and when the rest of the users poll for changes, the server will tell them user X is editing field Y, and use JavaScript to lock the field.
Note that this method shouldn't be used for critical security features! A user can easily bypass anything made in JavaScript, or on the client-side in general. You should validate on the server side as well, and not accept input on a field which is already being typed in.
I'm creating a PHP Web application, which would involve:
1) Users opening a record
2) Users making changes to the record
3) Saving changes to the record
Since this is a multi-user application, I want to prevent situations where two users have the same record open at the same time, and one user's changes overwrites the next, preferrably by enforcing some sort of locking method when a record is opened that automatically unlocks when the user navigates away from the page.
By record, you mean SQL records? If so, you could add another column isOpen. Set it to 1 as long as someone else has it open, and in that case, do not serve it to anyone else.
In situations like this, it works best to also implement a timeout mechanism, where a record can be open only for 'x' min before being forcibly closed.
(Edit: This answer is assuming you want to keep a record locked the entire duration a user is viewing the info fetched from the table. If you want to lock a record only for the instant that a read/write operation is occuring on that record, MySQL engines have inbuilt mechanisms for that)
In response to your comment
To make a record accessible to others when the active user navigates away, off the top of my head, I can think of two ways to achieve it:
Allow the timeout mechanism to take care of it. Depending on your scenario, a short enough time window could work fine.
In addition to the timeout, also implement a heartbeat mechanism - an Ajax script on the page polls the server letting it know the page is still open. If the user navigates away, the server recognizes the skipped heartbeat, and unsets the record. In this case, the timeout would still take precedence. So, if the user leaves the window open and walks away, the server would still receive the heartbeat, but when the time window closes, the server unsets the record (despite still receiving heartbeats).
I use a field update_date. When user reads the record I write a cookie with this date. When user updates the record and submits the new data I'am adding WHERE update_date = '$my_escaped_date' AND id = '$the_edited_id' and if mysql_affected_rows is zero I'm showing error message that the edited data is old. It's not perfect as if you edit old data you must reenter it, but it does the job.
A locking method is exactly what is available in mysql:
http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
It's not automatic but it allows you to lock a table, do stuff and then unlock it again.
Be carefull tho' that the system does not become locked up if you forget to unlock a table or a user takes a long time to change something and you only unlock it when that user submits the form.
A better way might be to read data from the table and upon submission of the form, check to see if the data has not been altered. If it has you can notify the user of the changes and other wise you can lock the table, perform the changes and unlock it again.
You can add a field in_use to the records table,
when a user open that record update its value to 1 and when he saves it
update it back to 0.
If the value is 1 - the record is locked and won't be opened for other users.
For instance , in my system i allow the user to create a list and add some information into the list eg. name , address, phone...
And after create the list, it will be inserted into database, and in the page the admin can delete the list
The problem is when user editing the list, the admin deleted the list, then what will happen?
The only way is to check the database again before the edit submit to the database. However, If there are a lot of form, a lot of input, how can i check each field , there is a lot of job if i have to check every field that is concurrent.
I am using php , mysql and pdo for query
Thank you
Well why wouldn't you simply check if the row exists in the corresponding table using it's primary key (id) ?
Basicly, you cannot avoid that situation. While the user edits the form, the user cannot find out if the form has been deleted.
One solution would be to have a flag up once the user starts editing the records that should prevent anyone from editing at the same time/deleting at the same time. Once the user submits the form, then the flag should be back to original value, so that other users/admins can edit/delet those records.
There is a second solution of using a service and check from time to time in the user's page via ajax if the records are still there, but if you have alot of inputs, that can be a little cumbersome to implement.
Basicly, you need to create something that resembles a transaction, aka. lock the records that are being edited. Be very carefoul, since you can end up with alot of locked records. You need to implement a time in which the user needs to finalize the "transaction". If there are locked records beyond that time, unlock them automaticly. Also beware of the fact that the user might exceed that time and you need to handle that situation also, since you will end up in the same state as your original problem.
PS: also you need to beware of informations that have been edited while the user was editig also, since those informations would be lost. For the edit part, i think i would go for a hashing approach to check the state before editing with the state after editing. from this point on, it's up to you to decide what to do.