Zend_Cache_Frontend_Page does not recognize output without echo - zend-framework

I am trying to fiddle around with Zend_Cache, so I added following code to my action (will be moved to bootstrap later, I guess):
$frontendOptions = array(
'lifetime' => 7200,
'debug_header' => true, // für das Debuggen
'default_options' => array(
'cache' => true,
'cache_with_get_variables' => true,
'cache_with_session_variables' => true,
'cache_with_cookie_variables' => true,
'cache_with_post_variables' => true,
)
);
$backendOptions = array(
'cache_dir' => '/tmp/'
);
$cache = Zend_Cache::factory('Page', 'File',
$frontendOptions, $backendOptions
);
echo "hej";
var_dump($cache->start('someid'));
Zend generates a cache file containing hejbool(false) now, but apart from that it does not cache my page. According to a German book about zend framework, false is correct when there is no cache available. true is only returned when a cache was found.
When I debugged within Zend_Cache_Frontend_Page.php directly, it went down to the bottom of the start()-method, meaning that nothing went wrong (id given) and no cache was found, so one had to be generated. This was done (I can see it in /tmp/), but without the needed content.
So why does not not cache the output from Zend_View, but only direct output via echo?
I do not call any explicit function to render the view, but this did not seem necessary anymore (my views are always rendered automatically according to controller and action). I tried it for both a standard XHTML template (index.phtml) and an RSS template (index.rss.phtml).
Any ideas? Do you need any other code fragments?

When using the Zend_Cache_Frontend_Page you have to enable the disableOutputBuffering option. The reason is that Zend_Cache_Frontend_Page uses ob_start with a callback and it has to be the first call to ob_start otherwise it leads to that strange behaviour you've encountered.
To enable it you can either set it in your Bootstrap with
Zend_Controller_Front::getInstance()->setParam('disableOutputBuffering', true);
or using the configuration file after your frontController-setup (here in the INI-style configuration):
resources.frontController.params.disableOutputBuffering = true

Related

Zend Framework Cache creates new file and doesnt load it

i'm having a little problem with Zend Framework Full Page Cache.
My current Bootstrap configuration looks like this:
$dir = PUBLIC_PATH . "/tmp/";
$frontendOptions = array(
'lifetime' => 6000000000,
'content_type_memorization' => true,
'default_options' => array(
'cache_with_get_variables' => true,
'cache_with_post_variables' => true,
'cache_with_session_variables' => true,
'cache_with_cookie_variables' => true,
),
'regexps' => array(
'^/.*' => array('cache' => true),
)
);
$backendOptions = array(
'cache_dir' => $dir
);
// getting a Zend_Cache_Frontend_Page object
$cache = Zend_Cache::factory('Page',
'File',
$frontendOptions,
$backendOptions);
$cache->start();
which worked perfectly before changing our development system to the live one.
Now if we enable the caching system it creates the correct cached file in the correct path but doens't load it.
So for every request another cache file is created but the old one NEVER gets loaded.
Maybe anyone has had this problems before and can give me a hint?
Thanks in advance!
there might be issue with permission to move from development environment to live.
The tmp directory is writable by myself and other users of the same group and also apparently Zend will access the files as another user. The solution was to chmod 777 on the folder, making it writable.
let me know if i can help you more.

Caching whole html output with zend

I am trying to cache everything that is output by layout script and controller's action script using Zend_Cache but it is not working correctly. All I get is
DEBUG HEADER : This is a cached page !
I got layout.phtml script and index.phtml script. Both produce html code.
In my IndexController i put
$frontendOptions = array(
'lifetime' => 7,
'debug_header' => true,
'regexps' => array(
'^/$' => array('cache' => true),
'^/index/' => array('cache' => true)
)
);
$backendOptions = array('cache_dir' => '../application/cache/');
$cache = Zend_Cache::factory('Page', 'File', $frontendOptions, $backendOptions);
if(!$cache->start('mypage')) {
}
How to get it working? I expect that html code should be saved in cache folder.
check this tutorial out Brandon Savage on Zend Cache, it's short and I think it's more current then the ZF docs.

Zend form in a popup (fancybox, lightbox....)

I am developping a web application using Zend and I ran out of ideas for a problem I am having. In just a few words, I am trying to have a contact form in a popup (Fancybox, lightbox, colorbox or whatever...). The whole thing works fine, in the sense that it shows up the contact form in the popup and allows to send emails. However, whenever there are errors (unfilled input or filled wrong), I couldn't get those errors to be displayed on the popup (it actually redirects me back to the form in a normal display (view+layout), to show the errors.
It is perhaps possible but I now thought that perhaps I could more easily bring my error message to a new popup (the contact page, filled unproperly, would lead to a error popup page...). I think this alternative could look cool but am having real trouble doing it. Now my real question is : Can we really make a form on a popup, using Facybox (Lighbox or any other actually ... just want my popup) and Zend? Any Guru outhere??
Thanks a lot
here is the code:
the link for instance:
<a class="popLink" href=" <?php echo $this->url(array('module'=>'default', 'controller'=>'contact', 'action'=>'sendmail')).'?ProID='.$this->proProfil->getProID(); ?>">Contact</a>
the action:
public function sendmailAction()
{
$this->_helper->layout()->setLayout('blank');
$request = $this->getRequest();
$proID = $this->_getParam("ProID");
$professionalsList = new Model_DirPro();
$proName = $professionalsList->getProInfo($proID);
$translate = Zend_Registry::get('translate');
Zend_Validate_Abstract::setDefaultTranslator($translate);
Zend_Form::setDefaultTranslator($translate);
$contactform = new Form_ContactForm();
$contactform->setTranslator($translate);
$contactform->setAttrib('id', 'contact');
$this->view->contactform = $contactform;
$this->view->proName = $proName;
if ($request->isPost()){
if ($contactform->isValid($this->_getAllParams())){
$mailSubject = $contactform->getValue('mailsubject');
if ($contactform->mailattcht->isUploaded()) {
$contactform->mailattcht->receive();
//etc....
the form:
class Form_ContactForm extends Zend_Form
{
public function init ()
{
$this->setName("email");
$this->setMethod('post');
$this->addElement('text', 'mailsubject',
array('filters' => array('StringTrim'),
'validators' => array(), 'required' => true, 'label' => 'Subject:'));
$mailattcht = new Zend_Form_Element_File('mailattcht');
$mailattcht->setLabel('Attach File:')->setDestination(APPLICATION_PATH.'/../public/mails');
$mailattcht->addValidator('Count', false, 1);
$mailattcht->addValidator('Size', false, 8000000);
$mailattcht->addValidator('Extension', false,
'jpg,png,gif,ppt,pptx,doc,docx,xls,xslx,pdf');
$this->addElement($mailattcht, 'mailattcht');
$this->addElement('textarea', 'mailbody',
array('filters' => array('StringTrim'),
'validators' => array(), 'required' => true, 'label' => 'Body:'));
$this->addElement('submit', 'send',
array('required' => false, 'ignore' => true, 'label' => 'Send'));
$this->addElement('hidden', 'return', array(
'value' => Zend_Controller_Front::getInstance()->getRequest()->getRequestUri(),
));
$this->setAttrib('enctype', 'multipart/form-data');
}
}
I would suggest implementing AJAX validation. This would allow for the form to be verified before it is submitted. ZendCasts has a good tutorial on how to accomplish this: http://www.zendcasts.com/ajaxify-your-zend_form-validation-with-jquery/2010/04/
Ajax requests are handled via the contextSwitch action helper. You can to specify the various contexts an action needs to handle (xml or json) in the init method of the controller as follows:
public function init()
{
$this->_helper->contextSwitch()
->addActionContext('send-mail', 'json')
->initContext()
;
}
The request url should contain a "format=json" appended to the query string. This will execute the action and send the response in json format. The default behaviour of JSON context is to extract all the public properties of the view and encode them as JSON. Further details can be found here http://framework.zend.com/manual/en/zend.controller.actionhelpers.html
I found a "probably not the prettiest" working solution, it is to indeed use ajax as mentioned in the previous zendcast for validation to stop the real validation (preventdefault), process the data return the result and if everything's ok restart it.

How to implement PayPal in Symfony 1.4 & Docrtrine

I want to use PayPal, Express Checkout, in a Symfony/Doctrine 1.4.8 the current plugins all seem to be in Beta and also somewhat over the top in the way they are implemented. I can follow the logic of the PayPal provided information and code although some items are a bit vague as to how i deal with them in Symfony.
Any class files are ok as i create a lib directory and rename the class and this gets instantiated. However i have some plain procedural PHP files i.e. expresscheckout.php and i am not sure where to put this to load as it doesn't seem to fit in the templates. Perhaps it goes in the actions?
I am not looking for a line by line solution here (but if you have one feel free) but really a few pointers as to where the elements go. As i say i am still suffering form a bit of Symfony blindness.
Finally would i be better to implement a simple (is that possible?) plugin to handle this or group the paypal items in a module on their own?
What I did was write a class, I called it PaypalNvp, name the file PaypalNvp.class.php and put it in your /lib folder and put in functions for the Nvp Ops.
Then you can choose to either call the functions statically (change your class functions as needed) or initialize the class and call the functions...
So something like:
PaypalNvp::doExpressCheckoutPaypment($token, $payer_id, $amount, $currency, $payment_action);
or
$paypal = new PaypalNvp();
$paypal->doExpressCheckoutPaypment($token, $payer_id, $amount, $currency, $payment_action);
I don't think there is a set way of of saying which way is better... I use the latter method myself.
My class has a helper function in it that does the final communication operation with Paypal:
protected function api($data = array())
{
if (empty($data) || !is_array($data)) return false;
// INIT
$data = array_merge($data, array(
'VERSION' => $this->VERSION,
'PWD' => $this->PASSWORD,
'USER' => $this->USERNAME,
'SIGNATURE' => $this->SIGNATURE
));
array_walk($data, array(&$this, 'urlencode_walk'));
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->getUrl() . '/nvp',
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query($data)
));
$response = curl_exec($curl);
if (curl_errno($curl)) {
curl_close($curl);
return false;
} else {
curl_close($curl);
return $this->deformatNVP($response);
}
}
Main things you need to remember is to set the api method, e.g. SetExpressCheckout, and any required fields according to the PaypalNvp API

Zend cache doesn't kick in

Ok, here's the problem:
$frontendOptions = array(
'lifetime' => 7200,
'debug_header' => true, // for debugging, but it doesn't work...
'regexps' => array(
// Cache the static pages
'^/pages/' => array('cache' => true),
)
);
$backendOptions = $config->cache->backOptions->toArray();
// getting a Zend_Cache_Frontend_Page object
require_once 'Zend/Cache.php';
$cache = Zend_Cache::factory('Page',
$config->cache->backend,
$frontendOptions,
$backendOptions);
$cache->start();
This doesn't do anything at all. Page loading times are exactly the same and the folder indicated in $backendOptions is empty. What am I doing wrong?
By the way: $config->cache->backend reads "file".
Well, following my tradition of answering my own questions, here comes the answer, and a subquestion, if anyone knows what's going on:
Basically, this thing doesn't work out of the box if you happen to run something more advanced than Hello World. I had a cookie set and since it found a cookie, it refused to do anything about it, so one hour digging in the caching code I discovered that the magic needed was simply to set
'cache_with_cookie_variables' => true,
And well, since all cookies are more or less unique and I don't really want to care about them, I set
'make_id_with_cookie_variables' => false
So now it works flawlessly.
Thanks to Chris and smoove for taking the time out and now in hindsight your comments made a lot of sense. Naturally though, I didn't have any errors or warnings and "File" was indeed spelled with uppercase.
What I wonder now is if I can send a spike to delete the proper cache file upon certain circumstances. I can hammer it (copy the ID generator in the cache and unset() the proper target), but there might be a fancier solution. If you have any idea, let me know.
Please go to config/application.ini and set:
resources.frontController.params.disableOutputBuffering = true
If you are done with config/application.ini , just copy and past the code below and have fun.
Please do remember the temporary file ; I have used here servercache you can use temp or tmp or whatsoever.
$frontendOptions = array(
'lifetime' => 900,
'automatic_serialization' => true,
'default_options' => array(
'cache_with_get_variables' => true,
'cache_with_post_variables' => true,
'cache_with_session_variables' => true,
'cache_with_files_variables' => true,
'cache_with_cookie_variables' => true,
'make_id_with_get_variables' => true,
'make_id_with_post_variables' => true,
'make_id_with_session_variables' => true,
'make_id_with_files_variables' => true,
'make_id_with_cookie_variables' => true,
'cache'=>true
),
);
$backendOptions = array(
'cache_dir' => APPLICATION_PATH . '/servercache/'
);
$cache = Zend_Cache::factory('Page', 'File', $frontendOptions, $backendOptions);
$cache->start();