unplugged_web Posted June 19, 2014 Share Posted June 19, 2014 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 More sharing options...
justsomeguy Posted June 19, 2014 Share Posted June 19, 2014 It looks like you can check the length of the return value from getRecurringOrderProducts to see if there are any recurring products. Link to comment Share on other sites More sharing options...
unplugged_web Posted June 20, 2014 Author Share Posted June 20, 2014 How do I do that? I want it to still generate the pdf but without the date if a product isn't recurring Link to comment Share on other sites More sharing options...
justsomeguy Posted June 20, 2014 Share Posted June 20, 2014 The count function tells you how many elements are in an array.http://www.php.net/manual/en/function.count.php Link to comment Share on other sites More sharing options...
unplugged_web Posted June 23, 2014 Author Share Posted June 23, 2014 I've had a look at that but I'm not sure if it's the right thing though - what I want to do is if the product is a Bill (recurring products are an invoice) then it just skips that part of the code. Link to comment Share on other sites More sharing options...
justsomeguy Posted June 23, 2014 Share Posted June 23, 2014 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 More sharing options...
unplugged_web Posted June 23, 2014 Author Share Posted June 23, 2014 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 More sharing options...
justsomeguy Posted June 23, 2014 Share Posted June 23, 2014 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 More sharing options...
unplugged_web Posted June 25, 2014 Author Share Posted June 25, 2014 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 More sharing options...
justsomeguy Posted June 25, 2014 Share Posted June 25, 2014 $ops = $this->getRecurringOrderProducts();if (count($ops) > 0) { // recurring products}else { // no recurring products} Link to comment Share on other sites More sharing options...
unplugged_web Posted June 26, 2014 Author Share Posted June 26, 2014 $ops = $this->getRecurringOrderProducts();if (count($ops) > 0) { // recurring products}else { // no recurring products} Thank you that's perfect. I didn't quite understand what you meant before but definitely do now. Thank you Link to comment Share on other sites More sharing options...
unplugged_web Posted July 1, 2014 Author Share Posted July 1, 2014 (edited) 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 July 1, 2014 by thehappyappy Link to comment Share on other sites More sharing options...
justsomeguy Posted July 1, 2014 Share Posted July 1, 2014 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 More sharing options...
unplugged_web Posted July 2, 2014 Author Share Posted July 2, 2014 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 More sharing options...
justsomeguy Posted July 2, 2014 Share Posted July 2, 2014 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. Link to comment Share on other sites More sharing options...
unplugged_web Posted July 3, 2014 Author Share Posted July 3, 2014 (edited) 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 July 3, 2014 by thehappyappy Link to comment Share on other sites More sharing options...
justsomeguy Posted July 3, 2014 Share Posted July 3, 2014 Right, that's exactly what you're telling it to do. If any product is not recurring, then you tell PHP to just exit. Link to comment Share on other sites More sharing options...
unplugged_web Posted July 4, 2014 Author Share Posted July 4, 2014 That's what I tried but that just gave me a blank page when the order contained both recurring and non recurring products. It's fine if it does that when there's just non recurring products but not when there's both Link to comment Share on other sites More sharing options...
justsomeguy Posted July 7, 2014 Share Posted July 7, 2014 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 More sharing options...
unplugged_web Posted July 15, 2014 Author Share Posted July 15, 2014 I'm really sorry but how do I get it to just not add one off products then? I've tried so may different ways and either they don't work or just throw up errors Link to comment Share on other sites More sharing options...
justsomeguy Posted July 21, 2014 Share Posted July 21, 2014 This is really basic stuff, if you're going to be doing things with PHP then you need to study it. If you don't want it to do anything if the product is not recurring then remove the else block. Link to comment Share on other sites More sharing options...
unplugged_web Posted July 22, 2014 Author Share Posted July 22, 2014 (edited) 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 July 22, 2014 by thehappyappy Link to comment Share on other sites More sharing options...
justsomeguy Posted July 22, 2014 Share Posted July 22, 2014 I'm not sure what twig is, but you'll need to find out how to loop through an array and display each item there. Link to comment Share on other sites More sharing options...
unplugged_web Posted July 23, 2014 Author Share Posted July 23, 2014 (edited) 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 July 23, 2014 by thehappyappy Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now