Generate pdf files with dompdf engine in cakepdf plugin in CakePHP - dompdf

I am using CakePHP 2.7.3 and CakePdf 1.0.8. Am trying to generate pdf files for my Cake app, but the pdf I get just has some weird characters.
This is how the generated pdf looks like:
%PDF-1.3 1 0 obj > endobj 2 0 obj > endobj 3 0 obj > >> /MediaBox [0.0000.000 612.000 792.000] >> endobj 4 0 obj
[/PDF /Text ] endobj 5 0 obj > endobj 6 0 obj > endobj 7 0 obj > stream xœí™KoÛ8…÷ý\Îl8"ÅçÒq’¾•¤¨ ÌZµU[-,’… óë‡I\•Ýãôn¡‘#ˆÎ-ïˆä¥ò.“Y–‰ñïnóîb)Üó±wVj•‰åZüu-„
2•â•‹¶ýÙ‹y±/êv3”•Šåqµ|6f«WR;ód}9¤¶éÏ:H¯íñŠú×?®GI^—¼P|[ìÆ}*ïdëgÃ~Ûv#‡¶Jšxæë,†o?ÊÕ~dÉ“4×çî`qq;Ö‡\Z•æ&æí}Uöã»–ö
œÊd®Ü‹^•ôùøû+ÌíUSîEû]ì·¥¸/Ûûú„—Õ2z‡í·›aS•»Ë£úl•›ºê·ãÛÏò„Ë`‹Ò¹±Î‡˜¥£n:õuƘO•¹¨¥7„ÔL‘AílÕµ}ÿ좫Ö
4Ϸî%€AÃû²ÝtÅýö‘#MÎ[“k³•&•í™·Ry{^úÒ~©ÊU)¾=ŠçŠr~.ëúQPÀ•c¶éªÕP¤•!›wá×ÓƒF!ûdÖK—Q}È•v9t•îŸ³ÝÐW+Š2ï‹nè)hÈðeû˜ºè)`ÈbðÇ 2º)0“V”ÜCŸ˜Ê
ø}šëŸf²å¶k›“ùòÈY?µÛF,šö•b†Lóm¹«ú}GŽLdòãFQCFMÌfZKã(lŽÀ†Ä‹•˜-öCÑUE-«ªlè!Š.0/º¶·?ÊfSPü•ï¦ØSë
This is my view file View/Books/pdf/books_catalogue.ctp
<h2><?php echo __('Books Catalogue'); ?></h2>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th><?php echo 'Id'; ?></th>
<th><?php echo 'Name'; ?></th>
<th><?php echo 'Author'; ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($books as $book): ?>
<tr>
<td><?php echo h($book['Book']['id']); ?></td>
<td><?php echo h($book['Book']['name']); ?></td>
<td><?php echo h($book['Book']['author']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
My pdf layout: View/Layouts/pdf/default.ctp
<?php
require_once(APP . 'Plugin' .DS. 'CakePdf' .DS. 'Vendor' . DS . 'dompdf' . DS . 'dompdf_config.inc.php');
spl_autoload_register('DOMPDF_autoload');
$dompdf = new DOMPDF();
$dompdf->load_html(utf8_decode($content_for_layout),Configure::read('App.encoding'));
$dompdf->render();
echo $dompdf->output();
$dompdf->stream("Books Catalogue.pdf", array('Attachment'=>'0'));
?>
My Config/bootstrap.php
CakePlugin::load('CakePdf', array('bootstrap' => true, 'routes' => true));
Configure::write('CakePdf', array(
'engine' => 'CakePdf.DomPdf',
'pageSize' => 'A4',
'orientation' => 'landscape',
'download' => true
));
And my controller:
public function booksCatalogue(){
header("Content-type: application/pdf");
$this->pdfConfig = array(
'orientation' => 'portrait',
'filename' => 'Books Catalogue'
);
$books = $this->Book->find('all');
$this->set(compact('books'));
}
I have googled and tried to find some answers to no avail. Kindly Assist.

What you're seeing is the source of the PDF document. So your PDF is generating correctly but somewhere along the line the content type sent to the browser is set to text/html (it should be application/pdf). You're using the stream() method in your layout which will set the header appropriately (so you don't need to additionally set it in your controller).
dompdf does not exit() after sending the PDF to the client and so you might have output buffering enabled and CakePHP is doing something somewhere to set the content type after the PDF is generated. If this is the case you could just add an exit() to the end of your layout.
Better, however, might be to configure content-type/extension support in CakePHP. It's been a while since I've done this in CakePHP but I believe you would need to do some router and RequestHandler configuration.

Related

Image upload to specific folder in codeigniter

I've been trying to upload images to specific folder my scenario is I've upload controller in which I've do_upload function
public function do_upload($field_name) {
$field_name = 'image_title';
$page_id = $this->input->post('page_id');
$config = array(
'allowed_types' => '*',
'max_size' => '1024',
'max_width' => '1024',
'max_height' => '768',
'upload_path' => './uploads/'. $page_id
);
$this->load->library('upload');
$this->upload->initialize($config);
if (!is_dir('uploads'))
{
mkdir('./uploads/', 0777, true);
}
$dir_exist = true; // flag for checking the directory exist or not
if (!is_dir('uploads/' . $page_id))
{
mkdir('./uploads/' . $page_id, 0777, true);
$dir_exist = false; // dir not exist
}
else{
}
if (!$this->upload->do_upload($field_name)) {
if(!$dir_exist)
rmdir('./uploads/' . $page_id);
$this->data['error'] = array('error' => $this->upload->display_errors());
} else {
$fInfo = $this->upload->data($field_name);
$this->_createThumbnail($fInfo['file_name']);
return $fInfo;
}
}
/**********************************************************************************************/
function _createThumbnail($filename)
{
$config['image_library'] = "gd2";
$config['source_image'] = "uploads/" .$filename;
$config['create_thumb'] = TRUE;
$config['maintain_ratio'] = TRUE;
$config['width'] = "80";
$config['height'] = "80";
$this->load->library('image_lib',$config);
if(!$this->image_lib->resize())
{
echo $this->image_lib->display_errors();
}
I've index view file given as
<section>
<?php echo validation_errors(); ?>
<?php //echo form_open_multipart('admin/upload/index/' . ((isset($page->id)) ? $page->id : '' )); ?>
<?php echo form_open_multipart('admin/upload/index/'); ?>
<tr>
<td><h3>Upload Images</h3></td>
</tr>
<table class="table table-striped">
<tr>
<thead>
<tr>
<th>Image Name</th>
<th>View</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<?php if (count($images)): foreach ($images as $image): ?>
<tr>
<td><?php echo anchor('admin/upload/index/' . $image->id, $image->image_title); ?></td>
<td><?php echo btn_edit('admin/upload/index/' . $image->id); ?></td>
<td><?php echo btn_delete('admin/upload/index/' . $image->id); ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="3">There is no Image to display</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</section>
<section>
<table class="table table-striped">
<tbody>
<tr>
<td><h5>Select Page</h5></td>
<td><?php echo form_dropdown('page_id', $get_with_images, $this->input->post('page_id')); ?></td>
</tr>
<tr>
<td><h5>Select Image</h5></td>
<td>
<?php echo form_upload('image_title', set_value('image_title', $image->image_title)); ?>
</td>
</tr>
<tr>
<td><?php echo form_submit('submit', 'Upload', 'class="btn btn-success"'); ?></td>
</tr>
</tbody>
</table>
<?php echo form_close(); ?>
</section>
dropdown is populating from page controller what actually I needed is I want to upload image to the page selected from dropdown for example if "Contact" page is selected from dropdown I want to upload my image to "Contact" page and on the backend I want to create directory with the same name as selected in dropdown in my case I want "uploads/home/abc.jpg" and same for the other pages please advice the basic idea I will modify it with my own
You're already sending your pageid value as post. Use it at uploading config.
...
$config = array(
...
'upload_path' => './upload/' . $this->input->post('page_id')
)
You need to check if directory exists first, use isdir() PHP function, and if false, mkdir(), also PHP, with folder name and permission.
I'm not familiar anymore with CodeIgniter to tell you if there is some way to get written value of a <option> tag, but I would suggest to create a array with page ids and their respective name and look for the array's index by post value:
$page_name = [
0 => 'contact',
1 => 'home',
2 => 'user',
...
]
...
$config = array(
...
'upload_path' => './upload/' . $page_name[$this->input->post('page_id')]
)
EDIT: User had problems with thumb creation
With your update, you forgot to update also path of the thumbnail. So you must send the folder and filename:
function _createThumbnail($folder, $filename)
{
$config['image_library'] = "gd2";
$config['source_image'] = "./uploads/" $folder . "/" .$filename;
$config['create_thumb'] = TRUE;
$config['maintain_ratio'] = TRUE;
$config['width'] = "80";
$config['height'] = "80";
$this->load->library('image_lib',$config);
if(!$this->image_lib->resize())
{
echo $this->image_lib->display_errors();
}
Then you should call it as you were, replacing the parameters correctly:
$this->_createThumbnail($page_id, $fInfo['file_name']);

CakePHP Ajax Pagination

I am currently trying to get an ajax paginated list working. I think I'm close. When I click on the Previous, Next or individual page numbers, the correct results show but div.postsPaging is loaded with the paginated results along with Cake's default.ctp layout's header and footer. I've tried setting the layout to ajax in the displayPosts view or in the displayPosts action, but then the default layout doesn't appear at all (either inside or outside the div).
My question is, how can I load the postsPaging div with just the paginated results and not the header, footer or anything else in the layout. How can I get the results of the ajax request to not include the header and footer of the default layout?
The jQuery events attached to one of the page indexes and the Next button are:
$("#link-196981051").bind("click", function (event) {$.ajax({dataType:"html", success:function (data, textStatus) {$("#postsPaging").html(data);}, url:"\/AuthAdminCakeApp\/posts\/displayPosts\/page:2"});
return false;});`
$("#link-296431922").bind("click", function (event) {$.ajax({dataType:"html", success:function (data, textStatus) {$("#postsPaging").html(data);}, url:"\/AuthAdminCakeApp\/posts\/displayPosts\/page:2"});
return false;});`
My PostsController code looks like this:
class PostsController extends AppController {
public $helpers = array('Js' => 'Jquery');
public $paginate = array(
'limit' => 3,
'order' => array(
'Post.title' => 'asc'
)
);
public function displayPosts() {
$this->set('posts', $this->paginate());
}
// other actions
}
My paging element (paging.ctp) looks like this:
<?php
$this->Paginator->options(
array('update'=>'#postsPaging',
'url'=>array('controller'=>'posts',
'action'=>'displayPosts')));
?>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('id'); ?></th>
<th><?php echo $this->Paginator->sort('user_id'); ?></th>
<th><?php echo $this->Paginator->sort('title'); ?></th>
<th><?php echo $this->Paginator->sort('body'); ?></th>
<th><?php echo $this->Paginator->sort('created'); ?></th>
<th><?php echo $this->Paginator->sort('modified'); ?></th>
<th class="actions"><?php echo __('Actions'); ?></th>
</tr>
<?php
foreach ($posts as $post): ?>
<tr>
<td><?php echo h($post['Post']['id']); ?> </td>
<td>
<?php echo $this->Html->link($post['User']['id'], array('controller' => 'users', 'action' => 'view', $post['User']['id'])); ?>
</td>
<td><?php echo h($post['Post']['title']); ?> </td>
<td><?php echo h($post['Post']['body']); ?> </td>
<td><?php echo h($post['Post']['created']); ?> </td>
<td><?php echo h($post['Post']['modified']); ?> </td>
<td class="actions">
<?php echo $this->Html->link(__('View'), array('action' => 'view', $post['Post']['id'])); ?>
<?php echo $this->Html->link(__('Edit'), array('action' => 'edit', $post['Post']['id'])); ?>
<?php echo $this->Form->postLink(__('Delete'), array('action' => 'delete', $post['Post']['id']), null, __('Are you sure you want to delete # %s?', $post['Post']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<?php
echo $this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('separator' => ''));
echo $this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));
?>
The view for the displayPosts action looks like this:
<div id="postsPaging">
<?php echo $this->element('Posts/paging'); ?>
</div>
Edit:
I'm using CakePHP 2.2.5.
you have to use an ajax layout.
$this->layout = ($this->request->is("ajax")) ? "ajax" : "default";
You can also place this code snippet in AppController, for Ajax responses application wide.
public function beforeRender() {
$this->layout = ($this->request->is("ajax")) ? "ajax" : "default";
}
Also make sure you are loading the RequestHandler component.
var $components = array('RequestHandler');
Putting the above in your Controller or AppController will handle setting the layout to ajax.

Codeigniter - Export Database data in DOC format

I want to export data in my MYSQL Database into a DOC file using Codeigniter.
My code is as follows:
view named 'profile_top_view.php' where anchor is declared as :
<?php echo anchor('welcome/todoc','Export Posts to DOC File') ?>
controller named 'welcome.php' has function :
public function todoc() {
$id = $this->tank_auth->get_user_id();
$this->mpdf->useOnlyCoreFonts = true;
$filename = "POSTS";
$data['member'] = $this->s_model->alldata($id);
$this->load->view('export_posts_doc_view', $data, true);
$this->index();
}
A view named 'export_posts_doc_view.php', where a table will be created for the DOC file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Exported Posts in PDF File</title>
</head>
<body>
<?php
header("Content-Type: application/vnd.ms-word");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-disposition: attachment; filename=\"posts.doc\"");
?>
<div id="container">
<h4>Posts</h4>
<table border="1">
<tr>
<th>title</th>
<th>content</th>
<th>group</th>
<th>video_url</th>
<th>pic_path</th>
<th>name</th>
<th>phone</th>
<th>email</th>
<th>yes_no</th>
<th>single-line-text</th>
<th>para_text</th>
<th>pdf_file_name</th>
<th>add_photo_name</th>
</tr>
<?php
foreach ($member as $rows) {
?>
<tr>
<td><?php echo $rows['title'] ?></td>
<td><?php echo $rows['content'] ?></td>
<td><?php echo $rows['group'] ?></td>
<td><?php echo $rows['video_url'] ?></td>
<td><?php echo $rows['pic_path'] ?></td>
<td><?php echo $rows['name'] ?></td>
<td><?php echo $rows['phone'] ?></td>
<td><?php echo $rows['email'] ?></td>
<td><?php echo $rows['yes_no'] ?></td>
<td><?php echo $rows['single-line-text'] ?></td>
<td><?php echo $rows['para_text'] ?></td>
<td><?php echo $rows['pdf_file_name'] ?></td>
<td><?php echo $rows['add_photo_name'] ?></td>
</tr>
<?php
}
?>
</table>
<br> <br>
</div>
</body>
</html>
and also a model named 's_model.php', having function :
function alldata($id)
{
$this->db->select('');
$this->db->from('posts');
$this->db->where('user-id',$id);
$getData = $this->db->get();
if($getData->num_rows() > 0)
return $getData->result_array();
else return null;
}
If I keep that header there, then it is showing error as:
No webpage was found for the web address:
http://www.my_ip.com/project/welcome/todoc
But, if I remove the same header, it shows the things echoed in the controller.
I have got that header from the following URL:
exporting MS word documents using codeigniter?
Can anyone please let me know what should I do with that?
Thanks in advance..
Got the answer,
I made few changes in my controller 'welcome.php':
public function todoc() {
$id = $this->tank_auth->get_user_id();
$this->mpdf->useOnlyCoreFonts = true;
$filename = "POSTS";
$data['member'] = $this->s_model->alldata($id);
$this->load->view('export_posts_doc_view', $data);
}
see the code below i hope i will work for you
function exportexcel()
{
header("Content-type: application/vnd.ms-excel");
/* change the content-type depends upon our requerment */
header("Content-Disposition: attachment; filename=Sadhak.xls");
header("Pragma: no-cache");
header("Expires: 0");
$table = "your content goes here";
echo $table;
}

i want to send email with multiple database values

if($records->result()>0)
{
foreach ($records->result() as $user)
{
$username= ('first name='.$user->u_first_name.'<br/>'.'Last name='.$user->u_last_name.'<br/>'.'Email='.$user->u_email.'<br/>'.'Property Id='.$user->propertyid);
$username.="<br/>";
$username.="-------------------------";
$username.="<br/>";
$email_template = file_get_contents($this->config->item('base_url').'assets/email/email.html');
$email_template = str_replace("[[EMAIL_HEADING]]", $mail_content->subject, $email_template);
$email_template = str_replace("[[EMAIL_CONTENT]]", $username, $email_template);
$email_template = str_replace("[[SITEROOT]]", $this->config->item('base_url'), $email_template);
$email_template = str_replace("[[LOGO]]",$this->config->item('base_url')."assets", $email_template);
$this->email->message(html_entity_decode($email_template));
$this->email->send();
print_r($email_template);
this is my code
/* UPDATE */
You can use a view for your template like normal (passing in values), setting the third parameter as TRUE to return the html.
To send one email with all database records, just pass the entire result object into the view, the process it in the view using your standard foreach loops, etc..
E.g
if($records->result()>0) {
$email_template = $this->load->view('email_template', array('heading' => 'My Email Report', 'records' => $records->result(), TRUE);
$this->email->message($email_template);
$this->email->send();
print_r($email_template);
}
Then the view (/view/email_template) would be something like;
<h1><?php echo $heading; ?>
<p> Records;</p>
<table>
<?php
foreach ($records as $r) {
?>
<tr>
<td><?php echo $r->u_first_name; ?></td>
<td><?php echo $r->u_last_name; ?></td>
<td><?php echo $r->u_email; ?></td>
<td><?php echo $r->propertyid; ?></td>
</tr>
<?php
}
?>
</table>

Codeigniter Paginaton Next button is not working

I am trying to display information from database. I have set $config['per_page'] to 2, in my view file I can see the information I want but when I click on the next button it doesn't change anything. The database values remain same and the current page remains the first page too.
Would you please kindly help me figure out the problem?
Thanks in Advance :)
Controller:
function index($id){
$this->load->library('pagination');
$config['base_url'] = site_url().'Student_fee_status/index/'.$id;
$this->db->select('*');
$this->db->from('studentpayment1');
$this->db->where('studentid', $id);
$query = $this->db->get('');
$numrows=$query->num_rows();
$config['total_rows'] = $numrows;
$config['per_page'] = 2;
$config['uri_segment'] = '2';
$config['num_links'] = 20;
$config['full_tag_open'] = '<div class="pagination" align="center">';
$config['full_tag_close'] = '</div>';
$this->pagination->initialize($config);
$this->load->model('Mod_student_fee_status');
$data['records']= $this->Mod_student_fee_status->fee_status($id,$config['per_page'],$config['uri_segment']);
$data['main_content']='view_student_fee_status';
$this->load->view('includes/template',$data);
}
My Model :
function fee_status($id,$perPage,$uri_segment) {
$this->db->select('*');
$this->db->from('studentpayment1');
$this->db->where('studentid', $id);
$getData = $this->db->get('', $perPage, $uri_segment);
if($getData->num_rows() > 0)
return $getData->result_array();
else
return null;
}
EDIT
When the page first loads the link looks like this- http://localhost/sundial/Student_fee_status/index/1006/
but when I click on the next page it looks like this- http://localhost/sundial/Student_fee_status/index/1006/2
My View File:
<h1>Payment Status</h1>
<?php if(count($records) > 0) { ?>
<table id="table1" class="gtable sortable">
<thead>
<tr>
<th>S.N</th>
<th>Invoice ID</th>
<th>Transaction Description</th>
<th>Received Date</th>
<th>Debit</th>
<th>Credit</th>
<th>Balance</th>
</tr>
</thead>
<?php $i = $this->uri->segment(2) + 0; foreach ($records as $row){ $i++; ?>
<tbody>
<?php
$mydate= $row['period'];
$month = date("F",strtotime($mydate));
$year = date("Y",strtotime($mydate));
?>
<tr>
<td><?php echo $i; ?>.</td>
<td><?php echo $row['invoiceid'];?></td>
<td><a href="<?php echo base_url(); ?>student_fee_status/fee_types/<?php echo $row['paymentid']; ?>" rel="1" class="newWindow" >Total Fee For <?php echo $month ;?>, <?php echo $year ;?> </a></td>
<td><?php echo $row['received_date'];?></td>
<td><?php echo $row['totalamount'];?></td>
<td><?php echo "0";?></td>
<td><?php echo $row['totalamount'];?></td>
</tr>
<tr>
<td><?php echo $i; ?>.</td>
<td><?php echo $row['invoiceid'];?></td>
<td>Payment Received </td>
<td><?php echo $row['received_date'];?></td>
<td><?php echo "0";?></td>
<td><?php echo $row['amountpaid'];?></td>
<td>
<?php
$balance=$row['totalamount']-$row['amountpaid'];
if($balance>0){
echo "<font color=\"red\">$balance</font>";
}
else {
echo $balance;
}
?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<?php } ?>
<div class="tablefooter clearfix">
<div class="pagination">
<?php echo $this->pagination->create_links(); ?>
</div>
</div>
You are telling the pagination library to use $config['uri_segment'] = '2'; - the second segment of your uri.
When this is your url: http://localhost/sundial/Student_fee_status/index/1006/ I am guessing this is your base_url: http://localhost/sundial/
In this case your segments are:
Student_fee_status - your controller
index - the controllers method you are calling
1006 - the argument you are calling the controllers method with
this should be the argument for pagination
Try this
$config['uri_segment'] = '4';
instead of
$config['uri_segment'] = '2';
edit:
$data['records']= $this->Mod_student_fee_status->fee_status($id,$config['per_page'],$config['uri_segment']);
I think this line contains another error.
You pass your model the information which uri_segment is used by the pagination library. That should be 4 now. However, your model uses this value to specify an offset in your query. This means you always put an offset of 4 into your query. But I think what you really want to do is, pass the model the VALUE of the 4th uri_segment.
I would try this instead:
$data['records']= $this->Mod_student_fee_status->fee_status($id,$config['per_page'],$this->uri->segment($config['uri_segment']));

Resources