How to 'unset' session save handler? - session

For some reason I have to initialize session with default save handler.
Previous code explicitly sets custom handler with session_set_save_handler().
Changing previous code is not a realistic option in my situation, so does anyone know how to restore handler to default eg is there session_restore_save_handler or session_unset_save_handler functions or equivalents?

As of PHP 5.4 you can revert to the default session handler by instantiating the SessionHandler class directly:
session_set_save_handler(new SessionHandler(), true);

Here I have to answer on my own question since no one said anything:
First, there is no session_restore_save_handler or session_unset_save_handler given from PHP and (by so far) no native way to get things back as they were before. For some reason, PHP team didn't give us option to juggle with session handlers in this way.
Second, native session mechanism can be emulated with following code
class FileSessionHandler
{
private $savePath;
function open($savePath, $sessionName)
{
$this->savePath = $savePath;
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}
return true;
}
function close()
{
return true;
}
function read($id)
{
return (string)#file_get_contents("$this->savePath/sess_$id");
}
function write($id, $data)
{
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}
function destroy($id)
{
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
}
return true;
}
function gc($maxlifetime)
{
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
}
return true;
}
}
$handler = new FileSessionHandler();
session_set_save_handler(
array($handler, 'open'),
array($handler, 'close'),
array($handler, 'read'),
array($handler, 'write'),
array($handler, 'destroy'),
array($handler, 'gc')
);
register_shutdown_function('session_write_close');
This logic is closest to PHP's native session dealing one, but with , of course, unpredictable behavior in different circumstances. All I can right now conclude is that basic session operations is full covered with it.

Related

How to download a (large) file with a typo3 extbase controller action

I have a controller with a download action in typo3. For some time I have implemented it like this and it is working:
function downloadAction() {
// ...
// send headers ...
// ...
if ($fh = fopen($this->file, 'r')) {
while (!feof($fh)) {
echo fread($fh, $chunkSize); // send file in little chunks to output buffer
flush();
}
fclose($fh);
}
exit; // Stopp middlewares and so on.
}
I am wondering if I should/could return an object of type ResponseInterface in typo3 11. So it is obviously that exit stopps the middleware pipeline and other things and I don't really know if there are any side effects.
I tried the following to return a ResponseInterface :
function downloadAction(): ResponseInterface {
// ...
return $this->responseFactory->createResponse();
->withAddedHeader(...)
// ...
->withBody($this->streamFactory->createStreamFromFile($this->file))
->withStatus(200, 'OK');
}
The problem is that the solution with the ResponseInterface works only with small files. The problem seems to be in Bootstrap::handleFrontendRequest().
protected function handleFrontendRequest(ServerRequestInterface $request): string
{
// ...
if (headers_sent() === false) {
// send headers
}
$body = $response->getBody(); // get the stream
$body->rewind();
$content = $body->getContents(); // Problem: Read the hole stream into RAM instead of
// sending it in chunks to the output buffer
// ...
return $content;
}
typo3 tries to read the whole stream/file into RAM. That crashes the application.
So how should I trigger a file download these days with typo3?

Laravel 8 - Conditionally remember a value in cache [duplicate]

I'm developing one of my first applications with the Laravel 4 framework (which, by the way, is a joy to design with). For one component, there is an AJAX request to query an external server. The issue is, I want to cache these responses for a certain period of time only if they are successful.
Laravel has the Cache::remember() function, but the issue is there seems to be no "failed" mode (at least, none described in their documentation) where a cache would not be stored.
For example, take this simplified function:
try {
$server->query();
} catch (Exception $e) {
return Response::json('error', 400);
}
I would like to use Cache::remember on the output of this, but only if no Exception was thrown. I can think of some less-than-elegant ways to do this, but I would think that Laravel, being such an... eloquent... framework, would have a better way. Any help? Thanks!
This is what worked for me:
if (Cache::has($key)) {
$data = Cache::get($key);
} else {
try {
$data = longQueryOrProcess($key);
Cache::forever($key, $data); // only stored when no error
} catch (Exception $e) {
// deal with error, nothing cached
}
}
And of course you could use Cache::put($key, $data, $minutes); instead of forever
I found this question, because I was looking for an answer about this topic.
In the meanwhile I found a solution and like to share it here:
(also check out example 2 further on in the code)
<?php
/**
* Caching the query - Example 1
*/
function cacheQuery_v1($server)
{
// Set the time in minutes for the cache
$minutes = 10;
// Check if the query is cached
if (Cache::has('db_query'))
{
return Cache::get('db_query');
}
// Else run the query and cache the data or return the
// error response if an exception was catched
try
{
$query = $server->query(...);
}
catch (Exception $e)
{
return Response::json('error', 400);
}
// Cache the query output
Cache::put('db_query', $query, $minutes);
return $query;
}
/**
* Caching the query - Example 2
*/
function cacheQuery_v2($server)
{
// Set the time in minutes for the cache
$minutes = 10;
// Try to get the cached data. Else run the query and cache the output.
$query = Cache::remember('db_query', $minutes, function() use ($server) {
return $server->query(...);
});
// Check if the $query is NULL or returned output
if (empty($query))
{
return Response::json('error', 400);
}
return $query;
}
I recommend you to use Laravel's Eloquent ORM and/or the Query Builder to operate with the Database.
Happy coding!
We're working around this by storing the last good value in Cache::forever(). If there's an error in the cache update callback, we just pull the last value out of the forever key. If it's successful, we update the forever key.

Handle Exception From Within Method

I am implementing payments for my website using the API of an external service (ie. the service of the payment provider).
Let's say the user clicks 'BUY', and then we go to my controller which says something along the lines of:
public function buyFunction() {
$result = $this->ExternalService->pay();
if ($result->success == true) {
return 'We are happy';
}
}
I have also created the aforementioned externalService which has the pay() method:
class ExternalService {
public function pay() {
response = //Do stuff with Guzzle to call the API to make the payment
return response;
}
}
Now, sometimes things go wrong.
Let's say the API returns an error - which means that it throws a GuzzleException - how do I handle that?
Ideally, if there is an error, I would like to log it and redirect the user to a page and tell him that something went wrong.
What I've tried
I have tried using a try/catch statement within the pay() function and using abort(500) but this doesn't allow me to redirect to the page I want to.
I have tried using a try/catch statement within the pay() function and using return redirect('/mypage') but this just returns a Redirect object to the controller, which then fails when it tries to call result->success
I have tried using number 2 but also adding a try/catch block to the controller method, but nothing changed.
In the end, I have found two solutions. In both, I use a try/catch block inside the pay() method. Then I either return 0; and check in the controller if (result == 0) or I use abort( redirect('/mypage') ); inside the try/catch block of the pay() method.
What is the right way to handle this?
How to use the try/catch blocks?
In my experience, avoid handling exceptions let them pass through and handle them accordingly with try catches. This is the most pragmatic approach. Alternatively you will end up checking result is correct in weird places, eg. if ($result) {...}. Just assume it went good, except if the exception is thrown. Bonus: never do Pokemon catches with Exception $e unless you specifically needs it!
class ExternalService {
public function pay() {
try {
response = $client->get(...);
} catch (BadResponseException $exception) {
Log::warning('This should not happen check payment api: ' . $exception->getMessage());
throw new PaymentException('Payment did not go through');
}
return response;
}
}
Assuming you have your own Exception.
class PaymentException extends HttpException
{
public function __construct(?\Exception $previous = null)
{
parent::__construct(Response::HTTP_BAD_REQUEST, 'Unexpected error processing the payment', $previous);
}
}
This enables you to handle the flow in a controller, where it would make sense to handle the redirect. Sometimes if the exception is very integral or common to the web app, it can also be handled by the exception handler instead.
class PaymentController {
public function pay(PaymentService $service) {
try {
$payment = $service->buyFunction();
} catch (PaymentException $exception) {
return redirect()->route('app.payment.error');
}
return view('app.payment.success', compact('payment'));
}
}

How to turn off ConfirmableTrait in Laravel 5?

I need to switch off ConfirmableTrait in Laravel 5.
On my production server I have many jobs, some of them prompt alert "Do you really wish to run this command?" and for that reason job is failed.
Thanks in advance.
edit ConfirmableTrait like this
public function confirmToProceed($warning = 'Application In Production!', $callback = null)
{
return true;
}
second way override confirmToProceed method add in your job or create new trait file and use them
public function confirmToProceed($warning = 'Application In Production!', $callback = null)
{
return true;
}

Check if request was sent by Ajax or not

I am overriding a magento controller, before processing, is there a way to know if the request was sent by Ajax or not?
Thanks
Magento uses the class Zend_Controller_Request_Http for its requests.
You can use
if ($this->getRequest()->isXmlHttpRequest()) {
// is Ajax request
}
to detect Ajax requests this way.
At least
Prototype
Scriptaculous
jQuery
YUI
MochiKit
send the HTTP_X_REQUESTED_WITH header, according to the ZF docs.
Note though, "Ajax requests" means requests sent using XmlHttpRequest (and not using techniques like hidden <iframe>s, or Flash uploaders, or the like) to me.
Since this is subjective and your perception may differ: Magento itself seems to define "Ajax" in some more extended way than I do. Have a look at Mage_Core_Controller_Request_Http::isAjax():
public function isAjax()
{
if ($this->isXmlHttpRequest()) {
return true;
}
if ($this->getParam('ajax') || $this->getParam('isAjax')) {
return true;
}
return false;
}
Depending on your personal perception of "Ajax", this may (or may not) better fit your needs.
If Im not mistaken, magento is written using Zend Framework, therefor by using the Request object you can do
if($this->getRequest()->isXmlHttpRequest()){
// ajax
} else {
// not ajax
}
http://framework.zend.com/manual/en/zend.controller.request.html#zend.controller.request.http.ajax
Good luck! :)
Magento internally uses a mix of of both.
Zend Framework's isXmlHttpRequest() checks header.
public function isXmlHttpRequest(){
return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
}
In some cases magento uses isXmlHttpRequest() like in Mage_ImportExport_Adminhtml_ExportController::getFilterAction()
if ($this->getRequest()->isXmlHttpRequest() && $data) {
//code
}
In other cases it checks get parameter like in Mage_Catalog_Product_CompareController::removeAction()
if (!$this->getRequest()->getParam('isAjax', false)) {
$this->_redirectReferer();
}
Request Mage_Core_Controller_Request_Http::isAjax() checks for both
public function isAjax()
{
if ($this->isXmlHttpRequest()) {
return true;
}
if ($this->getParam('ajax') || $this->getParam('isAjax')) {
return true;
}
return false;
}
I would suggest to use Request object isAjax as it checks for Both.
The best mehtod is :
if (!$this->getRequest()->isAjax()) {
return false;
}
Just use pure PHP and never care:
public function isAjax()
{
return (boolean)((isset($_SERVER['HTTP_X_REQUESTED_WITH'])) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'));
}
You can use this:
if ($this->getRequest()->getParam('ajax')){
//Ajax related code
} else {
//Non ajax
}

Resources