HeadersAlready sent error when using TCPDF with Yii2 - yii2

I am getting HeadersAlreadySent Exception whenever I am printing PDF using TCPDF library, tried following suggestions found on other similar kind of questions, but in vain, none has worked
ob_start();
ob_end_clean();// All other content
return $pdf->Output($localFilePath, $destination);
Any help/pointers would be highly appreciated.

To resolve this error, go to the file called as "tcpdf_static.php" from the tcpdf vendor folder, and in function sendOutputData, replace echo $data with following lines to resolve the issue
ob_start();
ob_end_clean();// All other content
echo $data;
ob_end_flush();
die;

Related

Using Namespaces with spl_autoload_register

use PHPMailer\PHPMailer\PHPMailer;
require_once "PHPMailer/PHPMailer.php";
$mail = new PHPMailer(true);
This works great.
But when I try to autoload the classes using spl_autoload_register i get a
Warning: require_once(PHPMailer/PHPMailer\PHPMailer\PHPMailer.php): failed to open stream: No such file or directory
use PHPMailer\PHPMailer\PHPMailer;
spl_autoload_register(function($class){
require_once 'PHPMailer/' . $class . '.php';
});
$mail = new PHPMailer(true);`
I'm a bit confused since the autoloader now requires the full path to the PHPMailer class in the PHPMailer/PHPMailer namespace.
After doing some extended research it seems there are 2 ways to make this work.
when we use the "use" statement we tell spl_autoload_register() where the PHPMailer() class is located. In this example it is located in the PHPMailer/PHPMailer namespace.
In order for this to properly work we need to match the namespace to the folder structure. This means that the PHPMailer.php file must be located in the PHPMailer/PHPMailer folder.
We instantiate like this: $mail = new PHPMailer();
if we don't use the "use" statement we can tell the spl_autoload_register() where the class is when we instantiate the class.
$mail = new PHPMailer/PHPMailer/PHPMailer();

How do I declare that a function dies so it is detected by PhpStorm?

Background
I use several helper functions to stop the program flow and return data. For example, while most pages are HTML I occasionally return JSON and call
/**
* #param array|bool $response
*
* #die
*/
function jsonResponseDie($response)
{
header('Content-Type: application/json');
echo json_encode($response);
die();
}
The Problem
However, the calling function does not detect that there is a die statement and allows code to be present after it without warning.
function recievePush()
{
// Process a push request and respond with a json array.
jsonResponseDie(array('status' => TRUE));
echo 'This will never execute but PhpStorm doesn\'t know that';
}
The Question
How do I get PhpStorm to detect this function will die?
I did try a few items "#return die" or "#die" but these do not appear to be recognized. I also reviewed some documentation here but found nothing useful.
There is no special tags for such stuff in PHPDoc. PhpStorm also does not have any solution to that yet.
https://youtrack.jetbrains.com/issue/WI-10673 -- watch this ticket (star/vote/comment) to get notified on any progress.
UPDATE 2020-10-20:
The aforementioned ticket has been implemented and such functionality is now available since PhpStorm 2020.1.x version.
It is implemented using Advanced Metadata functionality (by creating separate PHP-like file for IDE eyes only): https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html#define-exit-points
<?php
namespace PHPSTORM_META {
exitPoint(\App\PageFlow::exitApplication());
}
Another example: as a result, the terminate() call with the bar argument provided will act as an exit point (another value will not trigger this). The last line of the run method will therefore be treated as unreachable:
exitPoint(Application::terminate('bar'));
P.S. From PhpStorm 2020.3 (to be released at some point in December or so this year) and using PHP Language Level = 8.0 you will be able to use PHP 8-style attribute #[NoReturn] right in your code instead of separate Advanced Metadata file (see WI-55531 (actual/original implementation) and WI-56103 (new attribute name) tickets).
I have a CodeIgniter 3.1.11 project that I wanted to implement an exitPoint on my SendJsonResponseAndDie() method which is in my myproject/ci/application/helpers/format_helper.php file.
For me, the solution was as simple as creating a meta directory in myproject, then creating a .phpstorm.meta.php file with the following contents:
myproject/meta/.phpstorm.meta.php:
<?php
namespace PHPSTORM_META {
function exitPoint($functionReference) {
return "exitPoint " . $functionReference;
}
exitPoint(\SendJsonResponseAndDie());
}
Hey presto, the "unreachable statement" text appears whenever I mouseover code that occurs after the function call anywhere in the project.
I wish, though, that the lines of code that cannot be reached would be dimmed so that I am visually drawn to the problem instead of requiring my hover event.
Some additional reading not mentioned in #LazyOne's answer: https://github.com/JetBrains/phpstorm-stubs/blob/master/meta/.phpstorm.meta.php

Namespace in php application

I am trying to manage my code in a sample code to learn. I have a sample application whose dir structure is as follow
-Sample
--bootstrap
--app
--class1.php
--class2.php
--class3.php
--config
--public
--resource
--readme
Everything works fine for me, able to autoload the classes and consume all the feature.
Now, I added namespace to my class definition.
namespace Sample\classes;
and my application won't work. In app needs I am trying to add
$obj = new Sample/classes/class1() //no class found
use Sample/classes as Sample
but still class not found error
Any help to consume namespace in this setup will be appreciated.
You need use backslash instead of slash
$obj = new Sample\classes\class1()

Yii2 UploadedFile saveAs() error handling

I have a controller action that accepts a file upload via ajax request and saves basic info about the file. If the save was successful, it then executes saveAs() to actually save the file to the filesystem. A little something like this:
if ($model->save()) {
$file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
}
Everything works great but I'd like to implement a check around the saveAs() so I can delete the just-inserted-record if the file, for some reason, can't be saved. I see that UploadedFile has a $hasError and $errors but if there is a problem saving the file code execution seems to stop at the saveAs(), not moving past it to actually let me handle the error.
Is there a way for me to catch saveAs() errors and perform some logic if there is a problem saving?
EDIT
I have tried assigning the return variable as in the following. However, this is how I first noticed that if a saveAs() error occurs, no code gets executed past the saveAs().
$saveResult = $file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
// Any code down here won't be executed if (for example)
// that "uploads" directory doesn't exist and the saveAs() fails
If this code throws an exception (directory not exist, not writable, etc.), you can use a regular try - catch block to handle that:
try {
$file->saveAs(...);
} catch (\Exception $e) {
...
}
Read official PHP docs about exceptions.
Another alternative is to add checks to prevent all most common possible errors:
if (!is_dir($uploadPath)) {
...
}
if such directory not exist, etc.
To get rid of that, I'd recommend to write tests and create that folders in deploy script (if they not exist).

Google Contacts API with Yii2

I am trying to use the Google contacts api from within Yii2.
Google provides a composer interface, so I added
"google/apiclient": "1.0.*#beta"
to my composer.json and did "composer update"
Now - how do I actually use this from within my Yii2 controller?
I have a working, standalone test script that works. In that, it does
require_once 'GoogleClientApi/autoload.php';
$client = new Google_Client();
However, this does not seem to work from Yii.
I've tried adding the require to my index.php file, as follows (copying autoload.php from a previous installation since autoload doesn't seem to come with the composer version - why would this be omitted?)
require(__DIR__ . '/../vendor/google/apiclient/autoload.php');
but this results in the following error when called in my controller:
Call to undefined function app\controllers\Google_Client()
I've read the post on http://www.yiiframework.com/doc-2.0/guide-tutorial-yii-integration.html but this doesn't make much sense to me.
Any help appreciated. Thanks
Your code is almost correct:
require_once 'GoogleClientApi/autoload.php';
$client = new \Google_Client();
The "\" is needed to indicate the class exists in the global namespace, as you are - in that piece of code - under the app\controllers namespace.