Is There A Downside To Calling Models From Helpers In CakePHP? - model-view-controller

A bit of context: I need to cache the homepage of my CakePHP site - apart from one small part, which displays events local to the user based on their IP address.
You can obviously use the <cake:nocache> tag to dictate a part of the page that shouldn't be cached; but you can't surround a controller-set variable with these tags to make it dynamic. Once a page is cached, that's it for the controller action, as far as I know.
What you can usefully surround with the nocache tags are elements and helpers. As such, I've created an element inside these tags, which calls a helper function to access the model and get the appropriate data. To get at the model from the helper I'm using:
$this->Modelname =& ClassRegistry::init("Modelname");
This seems to me, however, to be a kind of iffy way of doing things, both in terms of CakePHP and general MVC principles. So my question is, is this an appropriate way of getting what I want to do done, or should it ring warning bells? Is there a much better way of achieving my objectives that I'm just missing here?

Rather than using a Helper, try to put your code in an element and use requestAction inside of the element.
see this link
http://bakery.cakephp.org/articles/gwoo/2007/04/12/creating-reusable-elements-with-requestaction
This would be a much better approach than trying to use a model in your helper.

Other than breaking all the carefully-laid principles of MVC?
In addition to putting this item into an element, why not fetch it with a trivial bit of ajax?
Put the call in its own controller action, such that the destination URL -> /controller/action (quite convenient!)
Pass the IP back to that action for use in the find call
Set the ajax update callback to target within the element with the results of the call accordingly
No need to muck around calling Models directly from Views, and no need to bog things down with requestAction. :)
HTH

Related

How to differentiate between two dynamic url in Laravel

I have two dynamic url with simillar structure. For example, lets say, Product page and category page.
I have set both pages in
Route::get('/{product}', [UsersController:: class, 'productDetail']);
Route::get('/{category}', [UsersController:: class, 'categoryProducts']);
But when I click on url which suppose to go in category page, it redirect to product page only because of same structure. How I can differentiate both URLs for Laravel without altering their url structure?
I don't think this can be done without modifying the URL pattern at least a little bit.
If you do something like /50?type=category then in the show method you can use the query parameter to determine which table to look at. But you'll have to use the same show method and I don't recommend doing it this way.
I hope someone else will be able to shine some more light on the matter.
this is the best practice for your case to make yourapi Resful
Route::get('/product/{product-id}', [UsersController:: class, 'productDetail']);
Route::get('/product/categories, [UsersController:: class, 'categoryProducts']);
learn more about Restful api here https://restfulapi.net/resource-naming/
This should be done by calling index, update diff() function. You can try by using the below:
Route::get('/category/{slug}', 'site\categorycontroller#show')->name('category.show');
Route::get('/product/{slug}', 'site\productcontroller#show')->name('product.show');

Laravel, custom functions in for views

I am having someone create a bunch of templates (themes) for a website, and want to keep data passed to the views flexible.
For example, with the users in the system I want to be able to supply the top x users and the most recent x users. In my controller I don't want to pass this data to the view, because he might just need the top 5 users and I am querying the top 10 - or worse, I might only get the top 5 and he wants the top 10.
I am thinking there would be two ways to do this.
1 - A view "helpers" file, which could contain functions like. getTopUsers($count) and getNewestUsers($count) which would do the model / repo call.
2 - Create a view presenter to keep these extra functions. I've had a look and there seems to be two main presenter packages - https://github.com/ShawnMcCool/laravel-auto-presenter and https://github.com/laracasts/Presenter
Maybe there is a better way?
There could be half a dozen of these, for various models...
I would pop some client side code into your views and access a route to a controller action (which returns JSON by default) and conditionally add that particular snippet into your view (via a variable passed to the view that determines if the person is logged in). Then you can apply an auth filter to your route to protect it.
Note: with this approach you can pass url parameters to your action. This means you can tell your controller to limit your results more easily.
This is a very interesting question, my friend. What I can think of is the following
1) cheap way, just query 10 or whichever the biggest number, and then pass a variable $count to the view or let view pass a variable to the sub view
2) api call, if you'd like to do AJAX call, then as others suggested, you could just design a new route, getData?count=5.
Normally it's not easy to meet all requirements, and practically speaking in the prototype stage, it'll be more cost-effective to write fixed function like getData5, and getData10, or just make two pages :) it'll be a lot faster than coming up another new architecture design and then realize in the end nobody really uses them.

How do I use continuations in FubuMVC

https://github.com/adymitruk/fubumvc/commit/083e1d593d4e797ac04fb493acd1e29a332cd303?w=1
It seems returning a continuation breaks the binding to the view. It used to work before I added the continuation. Now I get a blank page for the default view.
You're using the same input model for your get and your post, so when you transfer, you get into an endless loop. I'm surprised you don't get a stackoverflow. There must be some checking in FubuContinuation that breaks the loop.
You're using the input model as the view model which you (generally) shouldn't do.
Your form tag needs to be a
Also, it looks like due to the naming of your models and the folders, the default view conventions weren't matching up views to your actions. To get things working, I threw them all in the same folder (bad, I know).
You'll want to sort out the folders and namespaces before doing anything serious with this.
Here's the pull request which I was able to get working and posting and such:
https://github.com/adymitruk/fubumvc/pull/1

How to load the layout at runtime in Magento?

I know that we can design the layout in *.xml then in the action just invoke loadLayout, and renderLayout to render the blocks/views.
But, I have a question is:
- How can I load the layout at runtime?
If we have an action which does not really design its layout and will be decided how to render at runtime.
You can please consider the answer from the question for more clear.
Writing a new answer because it seems that you actually DO still want to render, you just want to render a different route's layout XML updates. I believe the _forward() method from Mage_Core_Controller_Varien_Action will allow you to do what you are describing with the least amount of pain.
You should add your action controller directory ahead of the catalog directory, create a ProductController with a viewAction, and check customer is not logged in - in this check you would call $this->_forward('customer','account','login');.
This approach though is going to require more effort in order to be usable, as I imagine that you want the user to be sent to the product page upon login. Have you seen Vinai Kopp's Login Only Catalog module? It should do this for you.
loadLayout() and renderLayout() just execute block output method toHtml() (usually) and take the resulting strings and apply them to the response object via appendBody(). In an action controller you can just call $this->getResponse()->setBody('response string'). How you build the string is up to you.
You can also use Mage_Core_Block_Flush to immediately send output to the browser without using the response object.

NoCaching A Small Part Of My CakePHP Page

I want to employ CakePHP's basic caching functionality on my site's home page. However, there is one element on the page that should display different data depending on the visitor's location, as determined by their IP address.
You can't wrap <cake:nocache> around variables that are set in the controller, which is where I was previously determining the location and getting the data. My question therefore is: where can I optimally set a (session?) variable to contain visitor location information before the controller? How can I use this information to populate an array of data for the nocached portion of the view, while completely sidestepping the controller action, which is no longer being called?
Any advice greatly appreciated!
Hmm, well, apparently CakePHP questions aren't of much interest to the world at large: only 8 views in 2 days :(
In any case I investigated a bit further and discovered that, while the <nocache> tags don't let you surround variables to make them dynamic, they DO allow you to make non-caching calls to elements or helpers. I therefore extracted the relevant part of my page into an element, and populated the data array by calling a helper function.
This did mean that I had to access the model from inside the helper with
$this->Modelname =& ClassRegistry::init("Modelname");
and I'm not sure this is necessarily the respectful CakePHP and/or MVC way of doing things, but at least it's some way towards a solution!

Resources