Jump to content

Creating pdf only working sometimes


unplugged_web

Recommended Posts

I'm working on a site that generates a certificate (a pdf file) when somebody places an order. There are two types of products that can be ordered, one is a one off product the other has a recurring fee for 12 months, 24 months or 36 months.

If somebody orders a products with a recurring fee then the pdf file is generated no problems. But if the product is a one off product then the pdf isn't generated.

I've been throughout the error log and it says:

PHP Notice: Undefined offset: 0 in /home/ubuntu/web/generated-classes/site/Order.php on line 189

and

 

PHP Fatal error: Call to a member function getContractLength() on a non-object in /home/ubuntu/web/generated-classes/site/Order.php on line 189

Line 189 is:

      $date->add(new DateInterval('P'.$ops[0]->getContractLength().'M'));

with the whole function being:

public function getExpiryDate() {      $ops = $this->getRecurringOrderProducts();      $date = $this->getGoLiveDate();      $date->add(new DateInterval('P'.$ops[0]->getContractLength().'M'));      $date->sub(new DateInterval('P1D'));       return $date;    }     public function getDeliveryOptionValue()    {      return self::$delivery_options[ $this->getDeliveryOption() ];    }   public function getRecurringOrderProducts()  {    $products = array();    foreach($this->getOrderProducts() as $op) {      if($op->getProduct()->isRecurring()) {        $products[] = $op;      }    }     return $products;  }

What I don't know how to do those is change the code so that if the product is a one off then skips that part and just sets the ExpiryDate as never.

I'd be grateful for any help with this. By the way I didn't build the site but its written with Silex (something I've never used before)

Thank you

Link to comment
Share on other sites

I know. The getRecurringOrderProducts returns an array of recurring products. If that array is empty, then there aren't any recurring products. Use that wherever you want to check if there are recurring products.

Link to comment
Share on other sites

I've tried to changing this:

public function getExpiryDate() {      $ops = $this->getRecurringOrderProducts();      $date = $this->getGoLiveDate();      $date->add(new DateInterval('P'.$ops[0]->getContractLength().'M'));    $date->sub(new DateInterval('P1D'));       return $date;    }

to this:

    public function getExpiryDate() {        if($this->getRecurringOrderProducts()==-1) {      $date = $this->getGoLiveDate();}        if($this->getRecurringOrderProducts()==1) {      $ops = $this->getRecurringOrderProducts();      $date = $this->getGoLiveDate();      $date->add(new DateInterval('P'.$ops[0]->getContractLength().'M'));      $date->sub(new DateInterval('P1D'));      return $date;}    }

but it then doesn't work and instead of working out the expiry date for recurring products it just has today's date rather than the date that should be being working out from this line

$date->add(new DateInterval('P'.$ops[0]->getContractLength().'M'));      $date->sub(new DateInterval('P1D'));
Link to comment
Share on other sites

getRecurringOrderProducts returns an array, why are you checking for -1 and 1? When is an array equal to -1? That is not going to do what you expect. There's also no reason to call that function 3 times, just call it once, save the return value, and test or use the value later.

Link to comment
Share on other sites

getRecurringOrderProducts returns an array, why are you checking for -1 and 1? When is an array equal to -1? That is not going to do what you expect. There's also no reason to call that function 3 times, just call it once, save the return value, and test or use the value later.

I'm sorry to be so dumb but how do I do that? I've only just started in this job and am trying to sort out somebody else's code. There's a lot of their code that I've already sorted but this is something I'm really stuck on and don't seem to be getting anywhere.

 

I really appreciate you helping with this.

Link to comment
Share on other sites


I'm really sorry and I'm sure I'm being a pain but my boss has now just said that she doesn't want to certificate to so on recurring products but I'm not sure how to do that.

I think I need to change this part:

public function generateGoLiveCertificate($app)    {      $filename = $this->getGoLiveCertificateFilename($app);      if (!file_exists($filename)) {        // Generate HTML        $html =  $app['twig']->render('order/golivecertificate.twig', array(          'entry'           => $this,          'products'        => $products=$this->getRecurringOrderProducts(),          'content_height'  => intval( (8*100*count($products))/95 )+1,          'domain'          => $app['config']['domain'],        ));        // Generate PDF        $snappy = new Pdf($app['wkhtmltox_bin']);        $snappy->setOption('orientation', 'landscape');        $snappy->generateFromHtml(utf8_decode($html), $filename);      }    }

The getRecurringOrderProducts array is this:

  public function getRecurringOrderProducts()  {    $products = array();    foreach($this->getOrderProducts() as $op) {      if($op->getProduct()->isRecurring()) {        $products[] = $op;      }    }     return $products;  }

I did try changing it based on what you'd said before, but only got errors saying there were no products.

The other part I need to do is add a false value here if the product isn't recurring:

function isLiveable()    {      $liveable = true;       if ($this->getGoLiveDate()) return false;       foreach($this->getOrderProducts() as $op) {        if($op->getProduct()->needCli() && (strtolower($op->getCLI())=='tbc')) {          $liveable = false;        }      }       return $liveable;    }

Thank you so much for helping me with this. I only started the job a couple of weeks ago and am trying to fix somebody else's code in a framework I've need used before.

Edited by thehappyappy
Link to comment
Share on other sites

I don't know the details of your application or what you're trying to do. I can't do your job for you though, I'm happy to help people learn how to program but I can't do people's work for them.

Link to comment
Share on other sites

I appreciate that but I don't even know where to start with changing this so that if a product isn't recurring it sets liveable to false. Everything I try returns an error saying that there's no value.

 

function isLiveable()    {      $liveable = true;       if ($this->getGoLiveDate()) return false;       foreach($this->getOrderProducts() as $op) {        if($op->getProduct()->needCli() && (strtolower($op->getCLI())=='tbc')) {          $liveable = false;        }      }       return $liveable;    }
Link to comment
Share on other sites

I don't understand, I've already showed you how to check for recurring products, couldn't you do the same there? If your job is programming PHP you should really know how to do this stuff.

I did try to do what you said but then I get a blank page if the order has a non recurring product.

 

My job is actually as a straight HTML developer but I do have a limited knowledge of PHP. This is is built using Silex and before I'd started my job I'd never even heard of it.

 

I did this based on what you showed me before, but as I say if the only contains a non recurring product (whether it's only a non recurring product or a mix of both) then the page is blank:

public function getRecurringOrderProducts()  {    $products = array();    foreach($this->getOrderProducts() as $op) {      if($op->getProduct()->isRecurring()) {        $products[] = $op;      }else {exit;}    }    return $products;  }
Edited by thehappyappy
Link to comment
Share on other sites

You are telling PHP to give you a blank page if any product is not recurring. That is what this does:

if($op->getProduct()->isRecurring()) {        $products[] = $op;      }else {exit;}
Right there, you are saying that if any product is not recurring, then just exit and do nothing else. The exit statement stops PHP from doing anything else, it just shuts down immediately and the response ends. That's why you're getting a blank page if any product is not recurring.
Link to comment
Share on other sites

I've managed to get it to display only recurring products but the problem now is that no matter how many recurring products the pdf only displays one. I've changed the code to this:

public function generatePdfCertificate($app)
    {
$products = $this->getRecurringOrderProducts();
if (count($products) > 0) {
      $filename = $this->getPdfCertificateFilename($app);
      if (!file_exists($filename)) {
        // Generate HTML
        $html =  $app['twig']->render('order/pdfcertificate.twig', array(
          'entry'           => $this,
          'products'        => $products,
          'content_height'  => intval( (8*100*count($products))/95 )+1,
          'domain'          => $app['config']['domain'],
        ));
        // Generate PDF
        $snappy = new Pdf($app['wkhtmltox_bin']);
        $snappy->setOption('orientation', 'landscape');
        $snappy->generateFromHtml(utf8_decode($html), $filename);
      }
    }
}

and in the twig file I changed it to this:

{% for op in products %}

but now it shows only one product. Is there a way of looping through the 'generatePdfCertificate' function? Maybe some way of using 'foreach'? I did try it myself but couldn't get it to work so don't know if I got something wrong? This is what I tried, but it didn't show anything.

public function generatePdfCertificate($app)
    {
$products = $this->getRecurringOrderProducts();
if (count($products) > 0) {
foreach($products as $products)
      $filename = $this->getPdfCertificateFilename($app);
      if (!file_exists($filename)) {
        // Generate HTML
        $html =  $app['twig']->render('order/pdfcertificate.twig', array(
          'entry'           => $this,
          'products'        => $products,
          'content_height'  => intval( (8*100*count($products))/95 )+1,
          'domain'          => $app['config']['domain'],
        ));
        // Generate PDF
        $snappy = new Pdf($app['wkhtmltox_bin']);
        $snappy->setOption('orientation', 'landscape');
        $snappy->generateFromHtml(utf8_decode($html), $filename);
      }
    }
}

I've also checked the $products to make sure it's showing the right content (I used var_dump($products) to do that) and it is getting the right type of product but only one of them

Edited by thehappyappy
Link to comment
Share on other sites

I thought I'd post the solution incase anybody else had the similar problem.

I changed the twig file to this:

<ul>        {% for op in products %}        <li>{{ entry.getExpiryDate|date("d/m/Y") }}</li>        {%  endfor %}      </ul>

and it now works perfectly.

BTW twig is the file format that Silex uses.

Edited by thehappyappy
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...