CakePHP - Best way to persist application state? - cakephp

I have an app that tracks and displays various stats for a local athletic league. One of my requirements is to be able to break down stats by game type, league id and location id. The user picks a value for each of those 3 items and then goes off to view various stats with the 3 variables stored in a session. This works fine, but my problem is that users can't link back to whatever stats they were viewing. I know I can extend the life of the session, but I'd rather pass the state of those 3 variables around in the URL so I can have the ability to link back to any specific stats page with any or none of those 3 variables defined.
Query strings seem like an obvious way to do this, but I can't tell if there's any way for me to 'automatically' append the query string to all links generated in the app, or if I manually need to go through and add the querystring parameters wherever I generate a link or do a redirect. That seems like the brute force approach and I feel like there must be a better way to do this sort of persistence that I'm missing. Any help appreciated!

For a number of reasons (linking, SEO...etc), use a URL, not sessions/cookies. And instead of IDs, use slugs instead:
www.mysite.com/league/football/youth/newyork
I'm sure there are many different ways to keep the url vars consistent across the board, but the way I can think to do it would be the following:
You can use Cake's route functionality to set each item to a variable and make nice looking URLs
In your AppController's beforeFilter(), set the Session of each item (type, league, location)
Make a custom MyHtmlHelper
in it, check if your Session for each contains data, and if it does, append to every link that needs it (could use only for specific controllers, actions...etc)
I hope there's a simpler way, but that's all I could think of offhand.

Related

pagination for the list secrets for logic apps

I am using List secrets activity to get all the secrets from key vault. I am only able to get first few values as pagination is not Woking for this activity. Is there any other way I can get all the secrets values from the logic apps.Right now I am only able to do for first page values only and as per Microsoft there is limitation of maximum 25 items.
I've managed to recreate the problem in my own tenant and yes, it is indeed an issue. There should be a paging option in the settings but there's not.
To get around this, I suggest calling the REST API's directly. The only consideration is how you authenticate and if it were me, I'd be using a managed identity to do so.
I've mocked up a small example for you ...
The steps are ...
Create a variable that stores the nextLink property. Initialise it with the initial URL for the first call to the REST API, it looks something like this ... https://my-test-kv.vault.azure.net/secrets?maxresults=25&api-version=7.3 ... and is straight out of the doco ... https://learn.microsoft.com/en-us/rest/api/keyvault/secrets/get-secrets/get-secrets?tabs=HTTP
In the HTTP call as shown, use the Next Link variable given that will contain the URL. As for authentication, my suggestion is to use a managed identity. If you're unsure how to do that, sorry but it's a whole other question. In simple terms, go to the Identity tab on the LogicApp and switch on the system managed status to on. You'll then need to assign it access in the KeyVault itself (Key Vault Secrets User or Officer will do the job).
Next, create an Until action and set the left hand side to be the Next Link variable with the equal to value being expression string('') which will check for a blank string (that's how I like to do it).
Finally, set the value of the Next Link value to the property in the response from the last call, the expression is ... body('HTTP')?['nextLink']
From here, you can choose what you do with the output, I'd suggest creating an array and appending all of the entries to that array so you can process it later. I haven't taken the answer that far given I don't know the exactness of how you want to process the results.
That should get you across the line.

How to configure angular ui-router state that will match any and all present query parameters?

The Problem:
I'd like a single ui-router state to match the following urls:
#/.../update?id
#/.../update?username
#/.../update?customerId&sandwichId
If/when the 'update' state is active (it's a routed component), the component's controller knows enough to expect which params will be there (via a provided array of Strings that should/will match whatever query params are in fact present).
Current Solutions (none of which I'm 100% happy with)
I could just leave the url at '#/.../update' with the implicit understanding that I cannot navigate to that url from anywhere but it's parent state, and just pass in its primary key fields as a component binding. The drawback obviously being if I just type the URL in my browser, it will not have enough information to load.
As per an example I found here, I defined my 'update' state with single query parameter: pkKeys. I then define pkKeys upon my state transition to be the entire query parameter string I desire. This effectively achieves what I am looking for. However, typing this just doesn't feel right:
#/.../update?pkKeys=username=test
Moreover, it looks ugly on the more complicated situations:
#/.../update?pkKeys=customerId%3D3ae2e6eb-3bf7-42f8-a09c-9c690c8dbe15%26sandwichId%3D2cb6d513-06a3-4aa4-93bb-e53d279d95cb
Ideal Target State
Ideally, I'm looking for a way to configure my state in a way that matches the above patterns of urls. I did not have much success with $location service, but something tells me that has something to do with it. It appeared to me that $location.search() was cleared whenever $state.go( ... ) was invoked.
Thanks for any help in advance! Happy to elaborate on anything that might not be clear. It's a rather unique problem set I find myself in here...
On Further Research
For reference, I'm using Angular UI Router 1.x. I have found they have the notion of dynamic parameters, which seems to nearly solve the problem I am encountering (see the GitHub issue for this change). However, where this fails me is the state configuration still expects you to list the dynamic parameter's name. As my query param names are data-driven, the set of names is not a finite set. So I need dynamic parameters...with dynamic names.

React-router: Passing data through routes

I'm trying to figure out the best way to pass data through my routes. I know I can use params but there are certain types of data that don't belong in params.
For example: I have an index page that displays a list of applications. Each application has a button next to it which will route you to the view for that application.
I want to pass the application itself to the Application handler. However, it doesn't make sense to pass the entire application through params. Though it does make sense to pass the application identifier to params (i.e. :id or :name)
So the way I think I should be doing this is pass the application identifier to params, then in the Application component search my ApplicationStore for the appropriate application given the identifier.
Though, wouldn't it be easier and faster to pass the application itself? Is there a way to do this. Is there a reason not to do this?
Here is some code:
<Link to="showApplication" params={{name: application.name}}>View</Link>
or
<Link to="showApplication" params={{application: application}}>View</Link>
Thanks in advance!
The problem is that when the person refreshes, or in some other way directly loads the url, it needs to show the correct view. Because URLs are just strings, you need to represent the route as a string. You can't (easily) shove an actual application into the url.
The job of a router is to take that string (the URL) and map it to the actual code (the handler), and provide any extra data (the params, query, and/or hash).
Your job as a router user is to ensure there's enough information in the URL for the router to pick the right handler, and for the handler to have enough information to do its job (e.g. which application to show).
If the url is something like mysite.com/showApplication, there's clearly not enough information.
If it's something like:
mysite.com/showApplication/React.createClass(%7Brender%3A%20function()%7Breturn%20React.createElement('div'%2C%20null%2C%20%22I'm%20an%20application!%22%7D%7D)%3B
i.e. putting an application in the url, that's too much information, and generally a very bad idea.
But mysite.com/showApplication/applicationName is just right :-)
I'll provide an easy and hacky way, have a global object which you use to share information across routes eg.
window.CONTEXT = {'share':'this'}
Note that it's quite important only to use this way if the object you want to share can be recreated by the route itself, as FakeRain mentioned above the route has to contain just enough information for it to give the user the same experience if they reload.
The only reason you'd use this is to save bandwidth if you need to request information for what you want to share but yet you don't want a huge link.

Generate nicer id from localstorage/collections

So I've dived into Backbone.js framework and I've finally came to the point where I play with models/collections.
Here's the thing. I'm using localstorage as database and my problem is I'm not statisfied to see my ids look like this:
id : "53ec77a0-8b06-c31b-d72c-a350741898d0"
Is there a simple solution to set the id's to a more proper look, like 1, 2, 3 or even like the cid. I've tryed it out with cid but it isn't good either because it changes everytime you fetch the data from localstorage...
Thanks in advance!
/Haris
Hmmm, I am not sure why you'd want to do that, it's really the adapter's job to define the IDs, and ensure their uniqueness, not yours!
If you look at the code of backbone's localstorage, you can see the line that is creating your issues here:
create: function(model) {
if (!model.id) {
model.id = guid();
model.set(model.idAttribute, model.id);
}
...
}
So, two ways to go about that:
Fork backbone localstorage to replace the call to guid() (which just generate random ids, it doesn't try to ensure uniqueness) by something nicer.
Give your own ID before calling save(). For the localstorage, it's kind of acceptable since there are no real constraints on the ids, but then it becomes your job to make it unique, especially across multiple running of your app [closing+reopening the browser] (you can keep the lastId in your local storage and increment it every time, to make it behave like a Primary Key with AutoIncrement in a DB, I guess)

CakePHP: Updating a session variable after save

I have a User object that, upon successful authentication, is tucked into the session (sans security info) for easy recall and for determining whether we have an authenticated user or anonymous session. There are several paths by which the user can alter some or all of his or her information and I'd like to keep that session value up to date. The obvious answer is to update the value in the afterSave() callback, but that, of course, violates MVC.
Is there another way of capturing every change in one place so that I don't have to drop session writes all over the place? I can't think of anything, nor have I been able to find any other ideas. Am I the only person trying to do something like this?
Thanks.
Final Solution: I marked neilcrookes' response as the answer, frankly, because there doesn't seem to be the better way. Since this way violates my OCD senses, though, I took a slightly different path. I decided to have my User::authenticate() method return the authenticated user object to the caller so it can do whatever it wants with it. One of the things that the callers "want" to do is to drop that value in the session. It's redundancy, but it's very, very limited. In my mind, that felt better than accessing the session from the model (though it's certainly a damned if you do, damned if you don't scenario).
//in users controller
if ($this->User->save()) {
$this->Auth->login($this->User->read());
$this->Session->setFlash[.. etc]
And for the record, I do not agree with the answer of neilcrooks, but I will refrain from feeding the troll.
Some might disagree but I'd screw MVC, do it in Model::afterSave() and use $_SESSION - test for the session before writing to it, in case it's not started for example you are saving against the model in a shell or something.
MVC is a general pattern - a guideline, you can bang your head against it trying to figure out how to achieve something that doesn't quite fit, or just do it another way and move onto to something more important.
Bring on the flames.
after save
Use Like this
$this->Session->write('Auth.User.mmid', $kinde['Kindle']['id']);
You should be able to just use AppController to create the necessary callback(s) that keep your session data up to date. So, for instance, you could have your User model afterSave() set a property called changed to true. Then in your AppController->afterFilter() you check that property and update the session data as necessary.
Alternatively, you could write a component through which to update your user info and also your session data. Then any controller that needs to change user info just needs to include that component.
There's no need to write redundant code or break MVC.

Resources