CakePHP - Can you make forms submit params as named params? - cakephp

So GET forms make the usual urls like
.../search/?q=apple
Can you make a form create urls like
.../search/q:apple/

Thanks, guys. I've found a different solution. I just submit the form as a POST and in the controller's action I read the post data and create a url with the post data as named params and then $this->redirect('...'); to it.

The methods to create these URL's can be found here: http://book.cakephp.org/view/842/url

If I understand you correctly, you're not looking to create a different URI, per se, but rather to serialize the form data in a different way. In other words, you're interested in modifying the query string rather than the URI itself.
As far as I know, that's the way that forms serialize their data and there's no way to truly override this behavior. If you really want to do this, I suspect you'll have to capture the submit event, manually serialize the form data into the format you want, append that format to the form's action value, make a custom request to the page (via location.href, etc.) and return false so that the form itself never actually gets submitted.
Of course, you could also submit via Ajax where you have a little more control.
I'm not aware of any other way to do what I think you're asking.

Related

What's the preferred way to go about using backbone with non-crud resources?

New to backbone/marionette, but I believe that I understand how to use backbone when dealing with CRUD/REST; however, consider something like results from a search query. How should one model this? Of course the results likely relate to some model(s), but they are not meant to be tied to said model(s).
Part of me thinks that I should use a collection using a model that doesn't actually sync with a data store through the server, but instead just exists as a means of a modeling a search result object.
Another solution could be to have a collection with no models and just override parse.
I assume that the former is preferred, but again I have no experience with the framework. If there's an alternative/better solution than those listed above, please advise.
I prefer having one object which is responsible for both request and response parsing. It can parse the response to appropriate models and nothing more. I mean - if some of those parsed models are required somewhere in your page, there is something that keeps reference to this wrapper object and takes models from response it requires via wrapper methods.
Another option is to have Radio (https://github.com/marionettejs/backbone.radio) in this wrapper - you will not have to keep wrapper object in different places but call for data via Radio.

Cascading dropdowns that keep state in the querystring

I am trying to build a page with three cascading dropdowns, lets say Brand, Model and Year, which is rather easy using something like Knockoutjs.
The thing is that I'd like to keep state in the querystring, so while making my choices, the URL is being updated also to something like '/Cars?Brand=Toyota' etc. (if the browser supports it).
Furthermore, if the users hits '/Cars?Brand=Toyota&Model=Corolla', I'd like the dropdowns to reflect that state.
At first I thought that something like this would be trivial with Knockoutjs, but is seems that it's not.
So, is there a way to 'bind' to querystring parameters using Knockoutjs? If not, is this something that can be done using a framework like Angular?
The easiest way would to just bind the values to your view model and then use jquery to update the querystring when the values change.
Updating existing URL querystring values with jQuery
If you then wanted to be really clever then i imagine you could move this code into a custom binding extension.
http://knockoutjs.com/documentation/custom-bindings.html

The best way for extending a model

According the Backbone.js documentation Model-parse does the following:
parse is called whenever a model's data is returned by the server, in
fetch, and save.
To augment models I've already loaded I use Model.parse(). I accomplish this by using fetch to make an additional request for data, then use that data to add properties to an existing model.
Example:
the fetch object is {age: 19}
after the parser will be {age: 19, isAdult: true}
When I perform the save request, in the PUT request I also have other parameters not needed (for example isAdult). I would like to have the original model (without additional parameters in PUT request).
What is the best way to achieve my goal in Backbone?
If I understand your question correctly ....
When backbone talks to a server using a save it sends a complete respresentation of the model. As the docs put it :
The attributes hash (as in set) should contain the attributes you'd
like to change — keys that aren't mentioned won't be altered — but, a
complete representation of the resource will be sent to the server.
So the default behavior is to send the complete model. If you want to implement you're own logic you're going to have to override the sync method. Dig through the expanded backbone code a bit and you'll see this comment above sync :
// Override this function to change the manner in which Backbone persists
// models to the server. You will be passed the type of request, and the model in question.
I would use the default implementation of sync as my starting point.

Preferred way of creating links with backbone.js

I'm trying to wrap my head around backbone.js but I'm finding it hard due to the lack of (IMO) good examples.
First of all, what is the best way of getting a link to an object.
If I want to get the edit url of an Album model I could do album.url() + '/edit', is this really the best way?
Also, I'm trying to make my application work 100% without javascript so I don't want my URLs/links to say /albums/#1/edit, I want it to be /albums/1/edit and override this in JS.
I'm thinking I create normal URLs and use jQuery.live to call router.navigate in backbone.js
I never got this to work however, when I call router.navigate('/albums/2', true) the URL changes but my show action is never called. If I refresh it's called so the route is matched.
What am I missing?
The basic answer, which is kind of frustrating, is "there is no preferred way!". Backbone.js doesn't tell you how to set up links, you can do it any way you like. I found this flexibility just as annoying as you do, at least at first.
So here's the way I'm approaching this on my current project, with the (big) caveat that this is just one of many ways to do things in Backbone:
For the most part, I don't use actual links. There's no explicit reason not to, but it means you have to keep track of a bunch of URL strings that have to be consistent. I would rather stick all the URL formatting in my routers and not deal with it elsewhere.
To open a new "top-level" view, like an editing screen, I set something that fires an event. In the application I'm currently working on, I have a global State model, and to open a new view I call state.set({ topview: MyTopView }). This causes the state object to trigger change:topview.
Any piece of the UI that needs to change when the top-level view changes has an update method bound to change:topview. When the event fires, they look at state.get('topview') and update as necessary.
I treat my routers as only marginally specialized parts of the UI - they're essentially views that render in the browser address bar, rather than the window. Like other views, they update the state object on UI events (i.e. a new URL), and like other views, they listen to the state object for changes that cause them to update. The logic that the editing screen has the URL albums/<albumid>/edit is fully encapsulated in the router, and I don't refer to it anywhere else.
This works well for me, but it adds an entirely new pattern, the global State object, to the Backbone structure, so I can hardly call this the "preferred" approach.
Update: Also note that .url(), in the Backbone idiom, refers to the model's URL in the back-end API, not the front-end URL (it's not like Django's get_absolute_url). There is no method in the default Backbone setup that gives you a user-facing URL for your model - you'd have to write this yourself.
Also, I'm trying to make my application work 100% without javascript; so I don't want my URLs/links to say /albums/#1/edit, I want it to be /albums/1/edit and override this in JS.
you can do exactly this w/ pushState. just enable it in your Backbone.history.start call:
Backbone.history.start({pushState: true})
this tells Backbone to use the HTML5 History API (a.k.a. "PushState"), which uses full URLs exactly like you're wanting.
read up on the history api here: http://diveintohtml5.ep.io/history.html
and I wrote up a 2 part series on using pushstate w/ the second part focusing on progressive enhancement in backbone, to do what you're needing:
http://lostechies.com/derickbailey/2011/09/26/seo-and-accessibility-with-html5-pushstate-part-1-introducing-pushstate/
and
http://lostechies.com/derickbailey/2011/09/26/seo-and-accessibility-with-html5-pushstate-part-2-progressive-enhancement-with-backbone-js/
hope that helps :)

cakephp requestHandler check for swf/flash

Is there a way to check if a cakePHP action is being called from an swf/flash movie like there is for Ajax using the requestHandler?
Put a named parameter in the URL that Flash is requesting:
eg. http://www.example.com/controller/action/flash:true
Check for this named parameter in your controller (or AppController) code:
if (isset($this->params['named']['flash'])) {
...
}
I don't believe so. A better option might be to create discrete controller actions that you only use from your Flash app.
Not the way I think you mean. The requestHandler can detect the type of request, but I think you're looking for the request source. It might be worth trying the getReferrer() method, but you may end up needing to add a click handler to the swf (if it's yours and you have that access).

Resources