I want to set cookie but unable to set
i have also used this public $components = array('Cookie');
i used in UsersController $this->Cookie->write('name', 'Larry');
echo on another controller echo $this->Cookie->read('name');
but there is no result
please suggest how to set cookie in cake php
thank Sanjib
It looks as if you used this tutorial for cookies: http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html
What you probably missed is setting up the cookieComponent, this of course is necessary in order for you to use cookies.
public $components = array('Cookie');
public function beforeFilter() {
parent::beforeFilter();
$this->Cookie->name = 'baker_id';
$this->Cookie->time = 3600; // or '1 hour'
$this->Cookie->path = '/bakers/preferences/';
$this->Cookie->domain = 'example.com';
$this->Cookie->secure = true; // i.e. only sent if using secure HTTPS
$this->Cookie->key = 'qSI232qs*&sXOw!adre#34SAv!#*(XSL#$%)asGb$#11~_+!##HKis~#^';
$this->Cookie->httpOnly = true;
$this->Cookie->type('aes');
}
If you comment out
$this->Cookie->type('aes');
you should find the problem gone.
In your AppController src\Controller\AppController.php
put var $components = array('Cookie');
or you can set and retrieve cookie using original PHP.
For people using CakePHP 4.x: Instead of using the cookie component, you now need to set a cookie to the Response object and fetch it via the Request object:
// Create cookie and set it to the Response object
$cookie = (new Cookie('name'))
->withValue('Larry');
$this->setResponse($this->getResponse()->withCookie($testCookie));
// Fetch a cookie's value from the Request object
$name = $this->getRequest()->getCookie('name'); // 'Larry'
Note that setting cookies will not work when using debug() or other output (e.g. echo), as headers cannot be sent if any output is already sent. You should get a warning about this as well.
For more information see this answer, or check the documentation on setting cookies and getting cookies
.
Related
I'm setting up a web page using cookies to determine if the user already logged in, using a cookie containing his id. Problem is : The cookie is either not written or the cookie collection is not updated.
I've tried reading the documentation, but it does not define the usage of CookieCollection.
Here's the function where i write my cookie :
function displayData(){
$id = $this->getRequest()->getSession()->read('id');
$cookies = CookieCollection::createFromServerRequest($this->getRequest());
if(!$cookies->has('id')){
$cookie = (new Cookie('id'))
->withValue($id)
->withExpiry(new DateTime('+999 year'))
->withPath('/')
->withDomain('break-first.eu')
->withSecure(true)
->withHttpOnly(true);
$cookies = $cookies->add($cookie);
}
// Other stuff
}
And where I try reading it :
function index(){
$cookies = $this->getRequest()->getCookieCollection();
dd($cookies);
}
I expect having a cookie named "id", but I don't have it. Only CAKEPHP and pll_language are showing up.
First things first, CakePHP provides authentication functionality with cookie authentication, you may want to have a look at that instead of driving a custom solution.
Cookbook > Plugins > Authentication
That being said, what you're doing there will create a cookie collection object, which however is just that, a lone object somewhere in space, it won't affect the state of your application, in order for that to happen you have to actually modify the response object.
However what you're trying to do there doesn't require cookie collections in the first place, you can simply read and write cookies directly via the methods provided by the request and response objects, like:
// will be `null` in case the cookie doesn't exist
$cookie = $this->getRequest()->getCookie('id');
// responses are immutable, they need to be reassinged
this->setResponse(
$this->getResponse()->withCookie(
(new Cookie('id'))
->withValue($id)
->withExpiry(new DateTime('+999 year'))
->withPath('/')
->withDomain('break-first.eu')
->withSecure(true)
->withHttpOnly(true)
)
);
And if you where to use a cookie collection for whatever reason, then you'd use withCookieCollection() to pass it into the response:
$this->setResponse($this->getResponse()->withCookieCollection($cookies));
If you run into strict typing errors, you could for example create a custom reponse class with an overridden Response::convertCookieToArray() method and cast the string to an integer there (make sure that PHP_INT_MAX covers your target date timestamp, 32-Bit incompatibility is why the fix that landed in CakePHP 4.x, probably won't come to 3.x), something like:
src/Http/Response.php
namespace App\Http;
use Cake\Http\Cookie\CookieInterface;
use Cake\Http\Response as CakeResponse;
class Response extends CakeResponse
{
protected function convertCookieToArray(CookieInterface $cookie)
{
$data = parent::convertCookieToArray($cookie);
$data['expire'] = (int)$data['expire'];
return $data;
}
}
You can pass that into the app in your webroot/index.php file, as the second argument of the $server->run() call:
// ...
$server->emit($server->run(null, new \App\Http\Response()));
See also
Cookbook > Request & Response Objects > Request > Cookies
Cookbook > Request & Response Objects > Response > Setting Cookies
I'm trying to integrate PayPal's IPN code into CakePHP 3.
namespace App\Controller;
use PayPal\Api\PaypalIPN;
class IpnController extends AppController
{
public function index()
{
$this->autoRender = false;
$ipn = new PayPalIPN();
// Use the sandbox endpoint during testing.
$ipn->useSandbox();
$verified = $ipn->verifyIPN();
if ($verified) {
/*
* Process IPN
* A list of variables is available here:
* https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNandPDTVariables/
*/
}
// Reply with an empty 200 response to indicate to paypal the IPN was received correctly.
header("HTTP/1.1 200 OK");
}
}
This is failing to validate on PayPal's end and I'm suspecting it has to do with setting the headers in the controller view.
Is there a way to set the header properly in CakePHP's controller.
I had this code running stand alone (in just a php file) and it seemed to work just fine.
You should not output any data in your controller action - that means you should not use echo, header() or any function or construct that would return anything to browser. If you do, you will encounter a "headers already sent" error.
If you want to set headers, you should use withHeader() or withAddedHeader() methods of Cake\Http\Response.
For status codes, you also have withStatus() method:
$response = $this->response;
$response = $response->withStatus(200,"OK");
return $response; // returning response will stop controller from rendering a view.
More about setting headers can be found in docs:
Setting response headers in CakePHP 3
Cake\Http\Response::withStatus()
Maybe that's not very Cakish, but actually one can send headers this way - it just have to be followed by die; or exit; to prevent app from further response processing.
Anyway, for sure your problem is not associated with headers. IPN seems to doesn't work properly with Paypal Sandbox. Maybe you should try it other way with ApiContext class?
I have this simple code in my AppController beforeFilter function, to set a cookie
$this->Cookie->name = 'MyCookie';
$this->Cookie->time = '1 hour';
$this->Cookie->domain = 'example.com';
$myCookie = $this->Cookie->read('my_cookie');
if ( empty($myCookie) ) {
$this->Cookie->write('my_cookie', 'cookieValue', true);
} else {
echo $myCookie;die;
}
So, as I refresh the page for the second time it should echo the cookie's value. But it does not. The output is nothing. Any ideas what can be the problem ?
I use cake 2.3.1. Cookie component is included. Debug level is 3 and there are no errors. I have checked the cake logs file - nothing there.
Thanks
I want to serve JSONP content with CakePHP and was wondering what's the proper way of doing it so.
Currently I'm able to serve JSON content automatically by following this CakePHP guide.
Ok, I found a solution on this site. Basically you override the afterFilter method with:
public function afterFilter() {
parent::afterFilter();
if (empty($this->request->query['callback']) || $this->response->type() != 'application/json') {
return;
}
// jsonp response
App::uses('Sanitize', 'Utility');
$callbackFuncName = Sanitize::clean($this->request->query['callback']);
$out = $this->response->body();
$out = sprintf("%s(%s)", $callbackFuncName, $out);
$this->response->body($out);
}
I hope it helps someone else as well.
I've as yet not found a complete example of how to correctly return JSONP using CakePHP 2, so I'm going to write it down. OP asks for the correct way, but his answer doesn't use the native options available now in 2.4. For 2.4+, this is the correct method, straight from their documentation:
Set up your views to accept/use JSON (documentation):
Add Router::parseExtensions('json'); to your routes.php config file. This tells Cake to accept .json URI extensions
Add RequestHandler to the list of components in the controller you're going to be using
Cake gets smart here, and now offers you different views for normal requests and JSON/XML etc. requests, allowing you flexibility in how to return those results, if needed. You should now be able to access an action in your controller by:
using the URI /controller/action (which would use the view in /view/controller/action.ctp), OR
using the URI /controller/action.json (which would use the view in /view/controller/json/action.ctp)
If you don't want to define those views i.e. you don't need to do any further processing, and the response is ready to go, you can tell CakePHP to ignore the views and return the data immediately using _serialize. Using _serialize will tell Cake to format your response in the correct format (XML, JSON etc.), set the headers and return it as needed without you needing to do anything else (documentation). To take advantage of this magic:
Set the variables you want to return as you would a view variable i.e. $this->set('post', $post);
Tell Cake to serialize it into XML, JSON etc. by calling $this->set('_serialize', array('posts'));, where the parameter is the view variable you just set in the previous line
And that's it. All headers and responses will be taken over by Cake. This just leaves the JSONP to get working (documentation):
Tell Cake to consider the request a JSONP request by setting $this->set('_jsonp', true);, and Cake will go find the callback function name parameter, and format the response to work with that callback function name. Literally, setting that one parameter does all the work for you.
So, assuming you've set up Cake to accept .json requests, this is what your typical action could look like to work with JSONP:
public function getTheFirstPost()
$post = $this->Post->find('first');
$this->set(array(
'post' => $post, <-- Set the post in the view
'_serialize' => array('post'), <-- Tell cake to use that post
'_jsonp' => true <-- And wrap it in the callback function
)
);
And the JS:
$.ajax({
url: "/controller/get-the-first-post.json",
context: document.body,
dataType: 'jsonp'
}).done(function (data) {
console.log(data);
});
For CakePHP 2.4 and above, you can do this instead.
http://book.cakephp.org/2.0/en/views/json-and-xml-views.html#jsonp-response
So you can simply write:
$this->set('_jsonp', true);
in the relevant action.
Or you can simply write:
/**
*
* beforeRender method
*
* #return void
*/
public function beforeRender() {
parent::beforeRender();
$this->set('_jsonp', true);
}
i am new with cake but i´ve somehow managed to get through so far. After i´ve figured out that html2pdf is a convienient way to produce pdf documents out of Cakephp, i´ve installed html2ps/pdf and after some minor problems it worked. So now i am coming now to the point that if i don´t modify my controllers beforeRender function like:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('download','view');
}
i just see my loginpage in the pdf i´ve created. Setting within my beforeRender function the $this->Auth->allow value opens obviously erveryone the way to get a perfect pdf without being authorized. The whole controller looks like this:
<?php
class DashboardController extends AppController {
var $name = 'Dashboard';
var $uses = array('Aircrafts','Trainingplans',
'Fstds','Flights','Properties','Person');
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('download','view');
}
function view() {
/* set layout for print */
$this->layout = 'pdf';
/* change layout for browser */
if> (!isset($this->params['named']['print']))
$this->layout = 'dashboard';
/* aircrafts */
$this->Aircrafts->recursive = 0;
$aircrafts =$this->Aircrafts->find('all');
$this->set('aircrafts',$aircrafts);
.... and so on....
$this->set('person_properties',$person_properties);
}
function download($id = null) {
$download_link = 'dashboard/view/print:1';
// Include Component
App::import('Component', 'Pdf');
// Make instance
$Pdf = new PdfComponent();
// Invoice name (output name)
$Pdf->filename = 'dashboard-' . date("M");
// You can use download or browser here
$Pdf->output = 'download';
$Pdf->init();
// Render the view
$Pdf->process(Router::url('/', true) . $download_link);
$this->render(false);
}
}
?>
So in my opinion the $Pdf->process call get´s the data by calling more or less the view, but this process is not logged in, or in other words not authorized to get the data i want to render into the pdf. So the question is now how to get it done by not opening my application to everyone.
Best regards, cdjw
Edit:
You could do something like this:
if($this->Session->check('Auth.User')) {
// do your stuff
} else {
// do something else
}
You could check for 2 things before rendering /view:
a valid session (a user is logged in)
a valid security token that you pass from your download action as a named parameter
For the security token, just make up a long random string.
As the PDF is rendered on the same server, the token will never be known in the open and provide sufficient security.
Hope this is a working idea for you.
I had this similar issue, and this is how I handled it...
I first noticed that the process call of the PdfComponent was doing a request from the same server, so I tricked CakePHP on allowing the view only for requests being made from the server itself.. like this:
public function beforeFilter() {
if ($this->request->params['action']=='view'&&$_SERVER['SERVER_ADDR']==$_SERVER['REMOTE_ADDR']) { // for PDF access
$this->Auth->allow('view');
}
}
You should put
$this->Auth->allow('download','view');
inside AppController. rather than place where are you using now.
function beforeFilter() {
$this->Auth->allow('download','view');
....
}