In Magento EE I need to redirect customers depending Origin country, browser lang and previous preference set in a cookie.
I have huge problems making it work with FPC.
I tryed to observe the controller_action_predispatch event, but FPC somehow caches my redirect instruction and customer is not redirected.
I then tried another solution: extending the run() method in Mage_Core_Model_App in order to perform operations before FPC starts to work.
Unfortunately, I don't know why, inside this method you can't access Mage::getModel(), Mage::helper(), Mage::getConfig() ecc
Can you help me please?
Thank you
I've recently been through exactly the same pain. You are on the right track;
controller_action_predispatch
Is the correct event to observe, and you can use this quite happily if you are redirecting to a category or product page with FPC enabled. The problem is the home page - which is a cms page. The cms page cache does not fire controller_action_predispatch. I got around this by adding this to my observer;
public function switchUser($event)
{
// CMS page bug, disable FPC to still use observer
$action = $event->getEvent()->getControllerAction();
if($action instanceof Mage_Cms_IndexController) {
$cache = Mage::app()->getCacheInstance();
$cache->banUse('full_page');
}
// do the rest of your code here
}
The blocks within the cms page will still cache so the page is still nippy, though obviously not as fast as it would be with full FPC enabled. Its a sound trade off in my opinion.
Related
I've already tried to find anything about that problem but I guess I either was not sure how to shortly describe the problem to find a solution or nobody else had that before which I can't think of. Maybe my thinking is wrong, too.
I have a stateless wicket 1.6 form with an ajax supporting panel (WebMarkupContainer with output id). The panel holds a dataview with paging navigator. The dataview itself is filled by a DataProvider.
The panel shows some entries from the database and below that is the navigator. by clicking any page on the navigator, the panel is refreshed (ajax) and shows content from that page. The page itself is not re-rendered by the browser.
When I now leave the page by navigating to another internal page (so basically when leaving the dataview-panel-page in any way) to open a detail page or so and then return to that dataview-page the navigator is resetted (because it's stateless I guess). The navigator can't remember which page to show and begins at the top of the first page again.
The question is: How can I solve this? I would like to i.ex. navigate to page 2 and then temporary leave the page for another internal page. When returning I want to be on page 2, focussed on the record where I clicked the link to "details" before. This also happens when I just open a new page in a new Browser tab.
Thank you!
Here's some code:
final WebMarkupContainer gamesPanel = new AjaxContainer("gamesPanel");
final DataView<Game> dataView =
new GameDataView("gameOverview", targetCurrencyModel, searchTextModel, gameFilterModel,
new GameDataProvider(searchTextModel, gameFilterModel, targetCurrencyModel));
dataView.setItemsPerPage(ITEMS_PER_PAGE);
gamesPanel.add(dataView);
final XNPagingNavigator navigator = new XNPagingNavigator("navigator", dataView);
navigator.setOutputMarkupId(true);
add(navigator);
You guys can try what I mean: The page I'm talking about is http://www.xbox-now.de. Just navigate to page 2, then click on details and return to main page.
I think you might use History API to push a new state when you click on navigation bar. In the new URL for the state you can include a parameter that indicates the index of the current navigator page.
You can customize your AJAX link in order to perform this operations when user click on it.
For more details on History API see Updating address bar with new URL without hash or reloading the page
I solved this in the NoWicket framework by introducing a model aware page cache which reuses page instances when hashcode/equals matches in the page model. You can see the implementation in the GitHub repo, try this implementation of the IPageFactory wrapper as a starting point, but it is more code involved there, just check out the code, debug the example and navigate the code to understand it better in order to apply it to your application. See your use case in action by trying this data table example in the documentation website (which you can also debug locally): http://invesdwin.de/nowicket/ajaxdatatable
Try changing the paging index, navigate to a different page and navigate back to the data table example page. You will still see the paging index that you left there.
Thank you guys for your replies. I've done it now another way. Used the base code from here and modified it in some ways. Added some nice css AttributeModifiers to indicate the actual page:
item.add(new AttributeModifier("class", new PageLinkCssModel(pageable, pageIndex, "active")));
Then I modified some code to add or reset the page parameter, that it's 1) used only once and 2) keeps all the actual page parameters which were there before adding own ones. So I am just appending the page number now. This way I can keep my initially mount path like www.foo.bar/path/path/path. Complete URL would now look like: www.foo.bar/path/path?page=123.
To pass my entered page (i.e. page=5) to the data provider I just had to override the providers iterator. It should start with the page I entered. Due to the ugly generated navigator URLs (which are extremly bad for SEO) I now have nice looking urls which are working independently what wasn't possible before. And that's also the reason why I could not get back to the correct page. The navigator URL was not lookup-able by wicket.
new DataView<GamePrice>("gamePriceOverview", new GameDetailDataProvider(gameId, targetRegion) {
#Override
public Iterator<GamePrice> iterator(final long first, final long count) {
return super.iterator(ITEMS_PER_PAGE * getCurrentPage(), count);
}
getCurrentPage() comes from the base template and gets the actual page number entered (if one is entered):
public long getCurrentPage() {
// -1 weil zero based
return getRequest().getQueryParameters().getParameterValue("page").toString() != null
? (getRequest().getQueryParameters().getParameterValue("page").toLong() - 1)
: 0;
}
So instead of having ugly SEO-unfriendly URLs which are also not compatible to work independant (directly enter the generated url) I now have the same URL I expect with an added page-parameter.
URL now would looks like:
http://localhost:8080/game/4249/de/doom-preorder?page=2
URL before was:
localhost:8080/game/4249/DE/doom-preorder?0-1.ILinkListener-gamePrices-navigator-navigation-2-pageLink
If I now go back from the detail page to the main index with active "Bookmarkable-Navigator", I correctly come back to the page and position where I left it (because of bookmarkable page links).
That's how I achieved this problem with a nice bonus: User- and SEO-friendly URLs.
I've never run into this before. on the /orders page there is the list of orders. When clicking the link it should take you to that order. However there is a long pause and the browser
re-displays the list even though the url is correct localhost/orders/2024 . If I look at the page source it shows the order, not the order list. If I refresh the page it shows the order not the order list. It does this in both firefox and chrome.
The only thing I can thing is that laravel is caching something.
My routes file:
<?
Route::get('orders/{id}',['as'=>'orders.show','uses'=> 'OrdersController#show']);
Route::get('orders', ['as'=>'orders.index','uses'=>'OrdersController#index']);
Does anyone have any idea about what's going on? I should add it does this from other computers also
EDIT: the show method. The order show file just display's "hello"
public function show($id)
{
return View::make('orders.show');
}
Looking at the source code for most browsers means refresh. To check your source code, open developers tool on Chrome, click the order link and then inspect your source code on the 'Elements' tab.
Somehow your order request in the first time is not being served by 'orders/{id}' and falling back to 'orders'. So do some tests:
1) Open a new browser tab and hit: localhost/orders/2024, what do you get?
2) Use dd() to understand where you are exactly:
public function show($id)
{
dd('on show!');
return View::make('orders.show');
}
public function index()
{
dd('on index!');
return View::make('orders.index');
}
3) Check the source code of your lists page, how those links are being generated? They might being somehow confusing Laravel routing system.
4) Create a link to a product manually and check if it does the same.
This didn't have anything to do with Laravel. It was twitter bootstrap. I haven't tracked down the problem yet but when I exclude twitter-bootstrap it works fine. Sorry, this should have been one of the first things I checked.
I have an observer watching the event sales_quote_item_set_product. In it, i am checking some conditions to make sure the item is still available. If it is not, i run this code:
Mage::helper('checkout/cart')->getCart()->removeItem($item->getId())->save();
Mage::getSingleton('message/session')->addError($item->getName() . ' is no longer available.');
The problem I'm having is if an item becomes unavailable and a guest is on a product view page, the cart says the item is in the cart, but the total for the cart is updated to reflect the product being removed. Also the error message is not displayed. If you go to another page or refresh the product view page the error message will display and the number of items in the cart will be correct.
So my thought is i need to run this code earlier in the execution cycle, but i have no idea what event i should be observing, or if i shouldn't be using an observer at all. I tried using sales_quote_load_after, but that caused a recursion error somehow. Can anyone tell me when/where i should run this code?
Another wild thought is could it be because i'm using database sessions instead of the file system?
The problem was that the error was being added after the messages block was rendered. I fixed it by adding a redirect to the cart page after the error was added.
$request = Mage::app()->getRequest();
if($request->getModuleName() != 'checkout' && $request->getControllerName() != 'cart' && $request->getActionName() != 'index') {
Mage::app()->getResponse()->setRedirect(Mage::getModel('core/url')->getUrl('checkout/cart/index'))
->sendResponse();
exit;
}
You didn't mention it, but this sounds like you're running code during an AJAX request. When you say
Mage::getSingleton('message/session')->addError($item->getName() . ' is no longer available.');
You're adding an error to Magento's session object. Every time a Magento page renders, it checks the session object for errors, and displays them all. This allows multiple developers to add multiple errors to the session, redirect Magento back to the original form.
This doesn't work during an ajax request, because (typically) the rendering process is skipped in lieu of a JSON object or simple, errorless HTML chunk being rendered (leaving the errors in the session).
Knowing what the full request cycle looks like (what's ajax, what's not) would help someone come up with a more concrete answer to your question.
I've got a very strange cache problem.
IÄve got one store with two languages. When i change the language from German to English, it's working the first time. So when i'm on side A(German) it switches to A(English). But.... if I change the page or the category... in example, from A to B and THEN i switch the language again, it redirects me back to A and not to B.
It's a very strage cache problem. I deactivated all cache options and afterwards it works perfectly but I cannot run a shop without any cache possibilities:
here's my shop: http://www.livewire-clothing.de/packagedetails/
Check out the page code. Switch the language and the page and check the code again.
This part never changes:
<select id="select-language" title="Ihre Sprache" onchange="window.location.href=this.value">
<option value="http://www.livewire-clothing.de/merchandise/k.html?band=78&manufacturer=55&size=39&___store=de&___from_store=de" selected="selected">Deutsch</option>
<option value="http://www.livewire-clothing.de/merchandise/k.html?___store=en&band=78&manufacturer=55&size=39&___from_store=de">Englisch</option>
</select>
It must be the cache.
Does someone got a solution for me or could help me out? Thank you very much.
The problem is most likely that you put the language switcher in the footer block. The footer block in Magento has block caching activated. If you take a look at Mage_Page_Block_Html_Footer , you will see a cache key defined (Magento 1.5):
public function getCacheKeyInfo()
{
return array(
'PAGE_FOOTER',
Mage::app()->getStore()->getId(),
(int)Mage::app()->getStore()->isCurrentlySecure(),
Mage::getDesign()->getPackageName(),
Mage::getDesign()->getTheme('template')
);
}
This means the block output will be cached in separate versions depending on the current store, design etc.
However, your language switcher links directly to the current page in each language. When the link is different for each page, your footer output will be different for each page. I would recommend simply disabling block caching for the footer block by overriding the block and remove the cache definitions, or by using a core/template block instead.
I am writing a custom Magento 1.5.0.1 one page checkout for my site following the instructions on this site:
http://inchoo.net/ecommerce/magento/magentos-onepage-checkout-in-a-nutshell/
In summary, I am calling these functions in order:
$checkout = Mage::getSingleton(‘checkout/type_onepage’);
$checkout->saveCheckoutMethod(‘guest’);
$checkout->saveBilling($billingAddress, false);
$checkout->saveShipping($shippingAddress, false);
$checkout->saveShippingMethod(‘flatrate_flatrate’);
$checkout->savePayment(array(‘method’=>’checkmo’));
// Extra part not on the site but saw it in the original magento onpage checkout controller
$checkout->getQuote()->getPayment()->importData(array(‘method’=>’checkmo’));
//
$checkout->saveOrder();
// Extra part not on the site but saw it in the original magento onpage checkout controller
$checkout->getQuote()->save();
//
The problem is that when the code is first run, the shipping method is not being set, I get a error saying that the shipping method was not set. However, just refreshing the page makes the order go through.
One solution was that right after setting the shipping method with saveShippingMethod, checking if it was set with:
Mage::getSingleton('checkout/type_onepage')->getQuote()->getShippingAddress()->getShippingMethod();
Which 100% of the time it is not, then redirecting it back onto the same page, which on the 2nd run the shipping method is set...
this seems to be such a stupid magento bug! any ideas on how to fix it with this redirection (i.e. page refresh)?
Maybe it is me not being extremely expert about magento, but I'm pretty sure you have to use setShippingMethod($method) instead of saveShippingMethod($method) when creating an order, you can check more here.