Parse.com PHP SDK - Refresh user data - Fetch command - javascript

I'm using the Parse.com PHP SDK on one of my pages. I seem to have a similar problem I faced on the iOS version but I easily solved that using the 'fetch' command.
The problem is when I edit information in my database, it does not update on my web page when I refresh the page. The user has to log out then log back in for the new data to be shown.
Here is how I'm getting the data:
<?php $u1=ParseUser::getCurrentUser()->get("auto"); echo $u1; ?>
Here is the documentation on the 'fetch' command but I don't understand how it works or how it is implemented: http://parseplatform.org/parse-php-sdk/classes/Parse.ParseUser.html#method_fetch
Does anyone know how to show the updated string values using this command or anything similar that would work?

The issue you're seeing is a cached object in your current session, specifically the current ParseUser. You can see that the php sdk attempts to find the current user from a variety of places, all effectively independent of the server-side copy.
You were in the right direction, you can use the fetch method to 'refresh' any ParseObject by updating it with any new changes from the database:
// get the current user
$user = ParseUser::getCurrentUser();
// fetch changes from parse
$user->fetch();
// get your newly set key/value pair
$isAuto = $user->get('auto');
Your user object will then be refreshed with the changes you need.

Related

Updating LocalStorage with the same data in the same time on multiple tabs causing problems

first of all i'm a beginer front end developer and i'm not a native english speaker so sorry for any mistake i made in my first question :D I'm working on project in Vue that was started by someone else. It uses websocket to display some notifications from server and i spotted a bug associated with this. The notifications are stored in object that pulls data from localStorage using VueUse's useStorage:
const state = reactive({
liveNotifications: useStorage("liveNotifications", []),
notificationsCount: 0,
});
And when data is received from ws it's being added to the beginning of the array like this:
connections.alerts.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data?.status) {
return;
}
state.liveNotifications.unshift(data);
state.notificationsCount += 1;
};
The problem is, when more than 2 tabs are opened and ws send some notifications, the localstorage starts acting weird like its trying to add the same objects over and over and notificationsCount is jumping (for example) from 2 to 3 and vice versa.
Is there any way to e.g. prevent app from updating localstorage multiple times if the data given from ws is the same on all tabs. Or maybe there's another way to make this work properly?
I've tried some solutions from web but to be honest i'm not really sure why is this happening and i didn't know what exactly i was supposed to look for so if someone has better knowledge than me and can help me understand i'm here to learn :)
The problem is: both tabs will read/write to the same "file".
The localStorage read-only property of the window interface allows you to access a Storage object for the Document's origin; the stored data is saved across browser sessions.
MDN - Window.localStorage
Suggestion here is to use sessionStorage instead:
[...] the difference is that while data in localStorage doesn't expire, data in sessionStorage is cleared when the page session ends.
Whenever a document is loaded in a particular tab in the browser, a unique page session gets created and assigned to that particular tab. That page session is valid only for that particular tab.
It sounds like you need a shared worker.
Since you are receiving the same data it is reduntant to keep two connections.
You should handle your websocket connection in a shared worker, then upon receiving the data save it to the localStorage, then post a message to the tabs to update the UI.

Cache API with MVC Views

I have a basic MVC form and I've been trying to use the Javascript Cache API to cache all my css, js, html files so that when users (people in the field) do not have reliable access, they can still use my web form. Obviously I'm using IndexedDB and service workers as well to check for a connection and save locally when a connection is not available, syncing when it is available.
I've gone through some tutorials and everything seems straightforward when dealing with caching actual, physical files (css, html, js). MVC is weird though since you're routing. I created the basix Index, Create, Edit, Details views. When I create an array of URL's to cache such as
var urlsToCache = [
'/App/Details',
'/App/Edit',
'/App/Create',
'/App/Index',
'/App/Content/bootstrap.css',
'/App/Content/site.css',
'/App/Scripts/jquery-1.10.2.js',
'/App/Scripts/jquery.form.js',
'/App/sw.js',
'/App/Scripts/bootstrap.js',
]
.. everything caches except for DETAILS and EDIT. Index and create cache fine. I'm actually surprised the latter two cache at all since they aren't physical files. I'm assuming Details and Edit don't cache because they don't work without querystring parameters.
Is it POSSIBLE to cache these two views at all? Or does anyone know of anything on NuGet that addresses this situation?
I changed this in the GET method for my Edit action to return an empty Model if there was no ID
if (id == null)
{
//return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
return View();
}
This allowed me to load the Edit page without a querystring variable and not get an error message. The page loads with no data but it allows me to cache it. At this point I suppose I would have to tell my service worker to check if the page is online. If it is, route the request normally, else query the local storage and manually plug the values into the fields.
So let this be a lesson to anyone creating Offline-enabled apps with MVC and using Cache API. Get rid of the lines that return bad request errors in your CRUD views if ID numbers aren't passed. Just pass back a blank model to the view (return View()). This allows you to cache your pages. And you'll obviously need to write code to handle the offline retrieval and presentation in code that executes when the page loads, but it will still allow you to utilize the MVC/Razor features when online.
One thing to note: "/App/Edit" will cache. If you load "/App/Edit/2", it won't match a url in your cache so you'll get an offline message. However, you can easily modify your Index page to send the ID via post. Just have a form on the page that goes to the Edit action and change the link to an underlined span with an onclick that sets the value of a hidden field to the ID. You'll have to pass another hidden field to let it know that it needs to retrieve instead of update (since the controller has different GET AND POST actions for Edit. The GET action is useless, but keep it for caching. You're retrieval that you normall would do int the GET is now going to be done in the POST with an if statement to check for your hidden field flag.

How to set a PHP object in session upon a hyperlink click

I have two PHP pages: One displays the information about an object retrieved from MySQL database and the other allows the user to edit it. The user is transferred from the first page (the view page) to the edit page upon clicking a hyperlink.
I would like to set the information retrieved from the database in session before passing on to the edit page so as to avoid an extra database call. How can I set an object in session upon a hyperlink click event? I know I could append the object as a variable to the GET request but is there a cleaner way than that?
Put the object into the session ($_SESSION['object'] = $object) when the page one loads (or when you retrieve the object from the database). This way you avoid a second call to the database. If you want to place it into the session upon the click event, a second call would be necessary, since you would have to make an AJAX call to a PHP script that retrieves the object. However, this may only make sense if the user is expected to edit that information, otherwise it is just storing data into sessions for no reason, which may also expose security bugs. If your database call doesn't retrieve millions of records, or you don't have hundreds of millions of users editing data in the same time, I can assure you that the impact on the performance by making a second call will go unnoticed.
Adding an object to the session:
$_SESSION['the_object'] = $object;
(Disclaimer: Will not work if the object contains any non-serializable components like closures)
Now when to do it? Actually, you have to do it on the page that shows the data, because if you do it later when the user clicks the edit link, this already triggers a new request which then would again go to the database - you'd have two requests (one for the list, one for the edit).
Generally, the edit link has the ID of the database entry to be edited. But pay attention to carefully check whether the user is allowed to have access or not, because MySQL will simply increment the ID, so it's easy to guess which IDs are valid. Anyone with a tiny bit of clue can modify a HTML form to tamper with IDs.
The approach with the session is somewhat easier: You only allow to edit what has been stored in the session, so the access control has to be done on the list page only.
For those who may be looking for a code snippet to help do this - here it is
Page 1 - this page just loads data from a DB and displays it in a non-editable mode on the screen. On this page we need an Javascript function that can be activated when the hyperlink is clicked
<script language="JavaScript" type="text/javascript">
function processEditLink(){
$.post('process_session_put.php', <?php echo "{S-Object:'".json_encode($obj_)."'});"; ?>
window.location.href = 'edit_object.php';
}
</script>
To explain the above code - we are taking an object (referred to as obj_) and encoding it into the JSON version by using the inbuilt function json_encode. Remember to ensure your object implements JsonSerializable in order to accomplish this. After that we are passing that JSON string as a POST URI parameter via AJAX to a secret page called process_session_put.php. This call is never visible to the end user and happens secretly when the hyperlink is clicked. The secret PHP page will decode the JSON string back into the PHP object and put it in session for all to use. Finally, once that function is complete, the window redirects to the actual edit page that can access data from session and populate the screen.
Next we should modify the hyperlink to trigger this Javascript function when it is clicked as below
<a class="edit-link" href="javascript:processEditLink(this);return false;">[Edit]</a>
Finally - the PHP page called process_session_put.php - which actually does the background work of decoding the JSON string passed to it back into the object format and putting it in session
<?php
if (!isset($_SESSION))
{
session_start();
}
// OBTAIN THE JSON STRING FROM POST URL, DECODE IT AND PUT IT BACK AS A OBJECT IN SESSION
$_SESSION["E-Object"] = json_decode($_POST["S-Object"]);
?>

Phonegap local storage returns empty result

On app's first load, I retrieve data from storage (Phonegap's WebSQL storage type). Phonegap storage results load fine. Until...
When I go to another page in the app:
Link
If I return back to that main page from the second page using window.location.href in Javascript, I retrieve the WebSQL data again (same function as before).
Phonegap Storage calls the success function (no error), but with an empty result set. It seems to be loading from a second database where I haven't stored anything into (see edit below).
If I force quit app and reopen, storage loads fine again, which shows me that the results in the DB are NOT being deleted.
I load the storage after ondeviceready is fired. What could be wrong?
Note:
1. This is not happening on simulators. only happening on real Android 4.0 device.
2. This app uses jQuery / jQuery Mobile.
function ondeviceready() {
db = window.openDatabase("test", "1.0", "test DB", 2000000);
// . . . //
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM table ORDER BY name', [], querysuccess, function(tx, e) {
errorAlert();
});
}), errorCB;
}
EDIT:
I'm noticing now that if I add a new row when app is first loaded, it stores in one database. Then, if I go to the second page and then back to the first page, and I add another row, it also stores, but in a separate database! (so that's what it seems to be doing). So strange, I see this happening. All my rows are saved and persistent, but the query returns a different group of results depending on whether I went to the second page or not...
Also:
The second page is having a jQuery error for some reason. I just created a blank page with a script link to jQuery, and there is an error. Strange... I wonder if this error is affecting the database? I'm trying to discover how to solve this error.
I've encountered an issue similar to this one before, but my problem was that I was trying to write to the same database from the Java side and the Javascript side. This is how I was able to solve it:
First I ran the app on an Android Simulator and used DDMS to access the databases and that is when I realised that the two were writing in different databases.
I changed from using WebSQL, to using proper SQLite database, and I started getting consistent results after that. It's a drop-in replacement for the phonegap's implementation of database storage, so no need to change your code much. Please see https://github.com/brodyspark/PhoneGap-SQLitePlugin-Android.
I think it's also important to note that WebSQL has some storage limitations, so you might be better off using SQLite that WebSQL. Please see: http://www.steveworkman.com/html5-2/standards/2011/the-limitations-of-websql-and-offline-apps/
Hope this helps :-)
What I've done is I now load the external HTML page through Ajax:
$.mobile.changePage("page2.html");
I also switched to pgsqlite as recommended.

ajax and local/session storage pattern

I'm building a web app that uses ajax to communicate with the server. Basically, the user requests a record, it comes back in json, it's added to the DOM and the user makes changes to it. When the user requests the next record, the current record is stringified and sent back to the server and the following record comes back.
All this works really well.... as long as the user keeps requesting records. However, I am wondering how to handle the situation where the user stops his work: how do I get the last record updated?
I thought of adding the working record to the local storage while he's editing it and at each edit, updating the local storage and if he logs on next time and there's still a record in there, ajax it when he logs on. The problem with his approach is that if another user logs on to the same computer, then when that new user logs on, he's updating the data of another user.
I thought of using the window.unload event also; but that doesn't solve the problem of the user closing his browser before the final update.
What are some good ways to handle this issue. Thanks for your suggestions.
I would consider a 'draft-like' feature. Where you could upload changes after a certain amount of time of no input, for instance, after 15 seconds of no input, push those changes.
If your app requires login, you could key the localStorage using their ids like so:
localStorage.getItem( "user13434" )
would retrieve data for user13434
localStorage.getItem( "user12345" )
would retrieve data for user12345
If the information is sensitive but not too sensitive you could add encryption, but it can be decrypted by experienced users which is why it must not be too sensitive.

Categories

Resources