I am trying to implement the Model-View-Controller architecture design pattern on my small project.
What I'm trying to achieve is to extend the basic view with a template.
Template base_view.phtml
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Bootstrap core CSS -->
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<title><?= $html_title ?></title>
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-expand-sm bg-light navbar-light">
<div class="container-fluid">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="#">Active</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#">Disabled</a>
</li>
</ul>
</div>
</nav>
<!-- Main content -->
<main class="container">
<!-- I am trying to load a template by calling this controller method -->
<?= $this->showSection('content'); ?>
</main>
<!-- Bootstrap core JavaScript
==================================================== -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous">
</script>
<script src="bootstrap/js/bootstrap.min.js"></script>
In the <main> element I am trying to load the template by calling the controller method
$this->showSection('content'); - Here is the home_view.phtml template
<!-- template base_view.phtml -->
<table class="table table-stripped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Date</th>
<th scope="col">Lastname</th>
<th scope="col">Name</th>
<th scope="col">e-mail</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<?php if (isset($rows)) : ?>
<?php foreach ($rows as $row) : ?>
<tr>
<th scope="row"><?= $row['id'] ?></th>
<td><?= $row['date'] ?></td>
<td><?= $row['lastname'] ?></td>
<td><?= $row['name'] ?></td>
<td><?= $row['email'] ?></td>
<td>Edit</td>
<td>Delete</td>
</tr>
<?php endforeach ?>
<?php endif ?>
</tbody>
My HomeController.php,
<?php
namespace App\Controllers;
use App\Core\BaseController;
use App\Models\MemberModel;
class HomeController extends BaseController
{
protected array $sections = ['content' => 'home/home_view.phtml'];
public function index(): void
{
// .... working with the model and loading data from the database ....
// I load the template, insert variables for home_view.phtml
$this->view(ctx: ['html_title' => 'Administration Panel', 'rows' => $db_data]);
}
}
The view() method logic is inside the BaseController abstract class
<?php
/* BaseController.php */
namespace App\Core;
abstract class BaseController
{
protected string $base_view = 'base_view';
protected array $section = array();
protected array $renderSection = array()
function __construct(){}
// I load base_view.phtml and simultaneously load home_view.phtml
// which is defined in class properties in HomeController.php.
// I load the content of the template into the class property `protected array $renderSection`
protected function view(string $section = '', array $ctx=[])
{
$this->context = $ctx;
$base_view = str_replace('\\', '/', self::DOCUMENT_ROOT) . "../Views/{$this->base_view}.phtml";
$_sections = $sections ?? $this->sections;
foreach ($_sections as $section => $file) {
$template = str_replace('\\', '/', self::DOCUMENT_ROOT) . "../Views/{$file}.phtml";
if (file_exists($template)) {
// loading the home_view.phtml template
ob_start();
require($template);
$this->renderSection[$section] = ob_get_contents();
ob_end_clean();
}
}
if (file_exists($base_view)) {
// Load base_view.phtml directly into the client browser.
extract($this->context);
ob_start();
require($base_view);
$body = ob_get_contents();
ob_end_clean();
echo($body);
}
protected function showSection(string $section)
{
return $this->renderSection[$section];
}
}
This solution only works when loading static content of template home_view.phtml. Not when rendering the template and dynamically loading the variables in the template.
Can someone advise me how to merge two views? How to correctly and efficiently render the home_view.phtml template in to base_view.phtml?
Thank you.
The problem seems to be solved.
I tried moving the extract() function above the foreach loop in the view method inside BaseController.php and everything now renders correctly.
Related
My error or success message is not in the right place, so I want to know how to get my message in the right place.
I have been searching the internet. I cannot find the right solution.
Here a photo what I mean.
<!DOCTYPE html>
<?php include('import_excel.php') ?>
<?php include('functions.php') ?>
<html lang="en" class=""><head>
<meta name="ac:base" content="/C:/xampp/htdocs/Angular-421-N-WORK-APP">
<meta charset="utf-8">
<title>N-WORK-USER | opslag-Sorting</title>
<meta name="description" content="app, web app, responsive, responsive layout, admin, admin panel, admin dashboard, flat, flat ui, ui kit, AngularJS, ui route, charts, widgets, components">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="../libs/assets/animate.css/animate.css" type="text/css">
<link rel="stylesheet" href="../libs/assets/font-awesome/css/font-awesome.min.css" type="text/css">
<link rel="stylesheet" href="../libs/assets/simple-line-icons/css/simple-line-icons.css" type="text/css">
<link rel="stylesheet" href="../libs/jquery/bootstrap/dist/css/bootstrap.css" type="text/css">
<link rel="stylesheet" href="css/app.min.css" type="text/css">
<link rel="stylesheet" type="text/css" href="css/component.css">
<script>
(function(e,t,n){
var r=e.querySelectorAll("html")[0];r.className=r.className.replace(/(^|\s)no-js(\s|$)/,"$1js$2");
}
(document,window,0)
);
</script>
</head>
<body>
<!-- content -->
<div id="content" class="app-content" role="main">
<div class="app-content-body ">
<div ng-controller="FullcalendarCtrl">
<!-- main header -->
<div class="wrapper-md bg-yello b-b">
<h1 class="m-n font-thin h3">Lijst werkkracht TL GL Database</h1>
</div>
<!-- / main header -->
<div class="wrapper-md" ng-controller="FormDemoCtrl">
<div class="panel panel-defaultgrd">
<div class="panel-headinggrd font-bold text-blue">
Uitslag
</div>
<div class="panel-body">
<div class="hbox hbox-auto-xs hbox-auto-sm">
<div class="container">
<div class="row">
<div class="col-md-12 control-label">
<button class="btn btn-info">Database invoegen</button>
<a class="btn btnx btn-orange" id="download-btn" target="_new"><i class="fa fa-download"></i> Export to Excel</a>
<form method="post" action="import_excel.php" enctype="multipart/form-data">
<div class="form-groupp" style="">
<input type="file" name="file-7" id="file-7" class="inputfile inputfile-6" data-multiple-caption="{count} files selected" multiple=""><label for="file-7"><span></span> <strong><svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17"><path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"></path></svg> Import Excel..</strong></label>
</div>
<a class="btnl"><button class="btn btn-info" style="">Upload</button></a>
</form>
<div class="table-responsive">
<table id="mytable" class="table table-bordred table-striped">
<thead>
<tr>
<th>#</th>
<th>MBU</th>
<th>Zone</th>
<th>Omschrijving</th>
<th>TL</th>
<th>GL</th>
<th>Stand in lijn</th>
<th>Station</th>
<th>MBU nr</th>
<th>WO stap</th>
<th>LOG stap</th>
<th>Q stap</th>
<th>RA stand</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<?php
$fetchdata=new DB_con();
$sql=$fetchdata->fetchdata();
$cnt=1;
while($row=mysqli_fetch_array($sql))
{
?>
<tr>
<td><?php echo htmlentities($cnt);?></td>
<td><?php echo htmlentities($row['MBU']);?></td>
<td><?php echo htmlentities($row['zone']);?></td>
<td><?php echo htmlentities($row['omschr']);?></td>
<td><?php echo htmlentities($row['tl']);?></td>
<td><?php echo htmlentities($row['gl']);?></td>
<td><?php echo htmlentities($row['stand_in_lijn']);?></td>
<td><?php echo htmlentities($row['station']);?></td>
<td><?php echo htmlentities($row['MBU_nr']);?></td>
<td><?php echo htmlentities($row['WO_stap']);?></td>
<td><?php echo htmlentities($row['LOG_stap']);?></td>
<td><?php echo htmlentities($row['Q_stap']);?></td>
<td><?php echo htmlentities($row['RA_stand']);?></td>
<td><button class="btn btn-info btn-xs"><span class="glyphicon glyphicon-pencil"></span></button></td>
<td><button class="btn btn-danger btn-xs" onclick="return confirm('Wil je bestand echt verwijderen?');"><span class="glyphicon glyphicon-trash"></span></button></td>
</tr>
<?php
// for serial number increment
$cnt++;
}
?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- / main -->
</div>
</div>
<!-- /content -->
<!-- footer -->
<footer id="footer" class="app-footer" role="footer">
<div class="wrapper b-t bg-light">
<span class="pull-right">2.3.0 <i class="fa fa-long-arrow-up"></i></span>
© 2018 Copyright.
</div>
</footer>
<!-- / footer -->
<script src="js/app.min.js"></script>
</body>
</html>
my other code import_excel.php
<?php
/**
* RaeCreated by Homensdigiworld.
* Admin: Stefaan
* Date: 26-03-2019
*/
include_once "app_opslag_database_tl_gl.php";
use Box\Spout\Reader\ReaderFactory;
use Box\Spout\Common\Type;
require_once ('connect.php');
require_once ('Spout/Autoloader/autoload.php');
if(!empty($_FILES['file-7']['name']))
{
// Get File extension eg. 'xlsx' to check file is excel sheet
$pathinfo = pathinfo($_FILES['file-7']['name']);
// check file has extension xlsx, xls and also check
// file is not empty
if (($pathinfo['extension'] == 'xlsx' || $pathinfo['extension'] == 'xls')
&& $_FILES['file-7']['size'] > 0 )
{
$file = $_FILES['file-7']['tmp_name'];
// Read excel file by using ReadFactory object.
$reader = ReaderFactory::create(Type::XLSX);
// Open file
$reader->open($file);
$count = 0;
// Number of sheet in excel file
foreach ($reader->getSheetIterator() as $sheet)
{
// Number of Rows in Excel sheet
foreach ($sheet->getRowIterator() as $row)
{
// It reads data after header. In the my excel sheet,
// header is in the first row.
if ($count > 0) {
// Data of excel sheet
$MBU = $row[1];
$zone = $row[2];
$omschr = $row[3];
$tl = $row[4];
$gl = $row[5];
$stand_in_lijn = $row[6];
$station = $row[7];
$MBU_nr = $row[8];
$WO_stap = $row[9];
$LOG_stap = $row[10];
$Q_stap = $row[11];
$RA_stand = $row[12];
//Here, You can insert data into database.
$qry = "INSERT INTO `users`(`MBU`, `zone`, `omschr`, `tl`, `gl`, `stand_in_lijn`, `station`, `MBU_nr`, `WO_stap`, `LOG_stap`, `Q_stap`, `RA_stand`) VALUES ('$MBU','$zone','$omschr','$tl','$gl','$stand_in_lijn','$station','$MBU_nr','$WO_stap','$LOG_stap','$Q_stap','$RA_stand')";
$res = mysqli_query($con,$qry);
}
$count++;
}
}
if($res)
{
echo "Your file Uploaded Successfull";
}
else
{
echo "Your file Uploaded Failed";
}
// Close excel file
$reader->close();
}
else
{
echo "Please Choose only Excel file";
}
}
else
{
echo "File is Empty"."<br>";
echo "Please Choose Excel file";
}
?>
I have that message : Undefined variable: _SESSION in C:\xampp\htdocs\import-excel_08\index.php on line 29
You are including the upload file at the top of your main page file.
<?php include('import_excel.php') ?>
It doesn't need to be included as it does nothing on that page, your form submits to that file.
Remove it from the top of that page and the message should go away.
Hi I have written code to delete a record (Just changing the status of the record from 1 to 0). Delete is working fine.
But the problem is, after deleting the record, it's not deleting immediately after I click on refresh button. it's removing the record from the list. This is the code which I have written for that.
Controller:
function index()
{
$data['records'] = $this->career_model->get_jobs_list();
$data['mainpage']='career';
$data['mode']='all';
$this->load->view('templates/template',$data);
}
function delete()
{
$this->career_model->delete($this->uri->segment(3));
$this->flash->success('<h2>Successfully deleted the record.<h2>');
redirect('careers');
}
Model:
function get_jobs_list()
{
$this->db->Select('jobs_list.*');
$this->db->From('jobs_list');
$this->db->where(array('jobs_list.status'=>1));
$q=$this->db->get();
if($q->num_rows()>0)
{
return $q->result();
}
else
{
return false;
}
}
function delete($jobs_id)
{
$data=array('status'=>0);
$this->db->where(array('jobs_id'=>$jobs_id));
$this->db->update('jobs_list',$data);
}
View:
<div id="mydiv">
<?php echo $this->flash->display('success', TRUE);?>
</div>
<script>
setTimeout(function() {
$('#mydiv').hide('fast');
}, 10000);
</script>
<div id="main">
<div class="full_w">
<div class="h_title">
<div class="lefttitle fl">
Categories
</div>
<div class="rightbutton fr">
<a class="button add" href="<?php echo site_url()?>/careers/add">Add </a>
<a class="button del" href="<?php echo site_url()?>/careers/deactivated">Deactivated </a>
</div>
</div>
<table>
<thead>
<tr>
<th scope="col">S.No</th>
<th scope="col">Job List</th>
<th scope="col" style="width: 65px;">Modify</th>
</tr>
</thead>
<tbody>
<?php if(isset($records) && is_array($records) && count($records)>0): ?>
<?php $i=0;foreach($records as $r):$i++;?>
<tr>
<td class="align-center"><?php echo $i;?></td>
<td><?php echo $r->job_name;?></td>
<td>
</td>
</tr>
<?php endforeach ;endif;?>
</tbody>
</table>
</div>
</div>
<div class="clear"></div>
try redirect('/careers', 'refresh');
from the docs
The optional second parameter allows you to force a particular
redirection method. The available methods are auto, location and
refresh, with location being faster but less reliable on IIS servers.
The default is auto, which will attempt to intelligently choose the
method based on the server environment.
Try with adding single quote in the model get_jobs_list() function.
change $this->db->where(array('jobs_list.status'=>1)); to $this->db->where(array('jobs_list.status'=>'1'));
I am making a portfolio website. In the menu I have the follwing itmes:
Home, Services, Portfolio(dropdown), About me, Contact.
Under projects I have to following folder structure:
Website root -> Portfolio -> projectName.html
When a menu item is active it has a blue background. As it is now, it is only html, so I have assign the correct header, everytime I make a new page there has to be under fx Portfolio. To summary up. I have 5 different headers, where each header have the specific choosen menu blue background attached.
I would like to use 1 header where the function is: If I click on "About me" the "active class" is called, which means the blue background is active. If I click projectName.html under Portfolio the Portfolio menu is active with a blue background.
The only way I know how to make that work is if there exist a user log in, and a session. Can I do something with CSS like this?
<!-- begin nav -->
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span>Tap me!</span>
</button>
<!-- begin logo in navigation -->
<a class="navbar-brand" href="index.php">
<img src="images/webdesign_Logo.png">
</a>
<!-- end logo in navigation -->
</div>
<div class="navbar-collapse collapse">
<ul class="nav nav-pills nav-main pull-right">
<!-- begin navigation items -->
<li class="active">Home</li>
<li>
Services
</li>
<li class="dropdown">
Portfolio
<ul class="dropdown-menu">
<li>
Portfolio 2 Column
</li>
<li>
Portfolio 3 Column
</li>
<li>
Portfolio 4 Column
</li>
<li>
Portfolio Single Item
</li>
<li>
Portfolio Single Full Width
</li>
<li>
Portfolio Single Options
</li>
<li>
Blog
</li>
</ul>
</li>
<li>
About Me
</li>
<li>Contact</li>
<!-- end navigation items -->
</ul>
</div>
</div>
</div>
</div>
</nav>
<!-- end nav -->
You can use css to perform that effect of a blue background when active:
yourDivId li:active{
background-color: blue;
}
yourDivId li:hover{
background-color: lightblue;
}
Using that css you can use JS to change the class to "active" when each li is clicked.
You can see what I mean here:
http://www.w3schools.com/cssref/sel_active.asp
Read this:
Tip: The :active selector can be used on all elements, not only links.
Tip: Use the :link selector to style links to unvisited pages, the :visited selector to style links to visited pages, and the :hover selector to style links when you mouse over them.
Note: :active MUST come after :hover (if present) in the CSS definition in order to be effective!
About the JavaScript part you can use this answer on this forum:
$('li a').click(function(e) {
e.preventDefault();
$('a').removeClass('active');
$(this).addClass('active');
});
From: Add & remove active class from a navigation link
first, i suggest create your nav in separate php file and include it in other file and.
second, use javascript code like this:
<script>
document.getElementById("**yourMenuItems**").children.item(<?php echo $SelectedMenu; ?>).classList.add("active");
</script>
thired, when include your nav file set $SelectedMenu variable.
I suggest to use PHP and this Class to get a basic template system and it also includes a function to add "active" class to menus.
<?php
/**
HOW TO USE THIS CLASS.
In every page:
-----------------------------------------------------------------------------------------------
<?php
require 'Page.php'
$page = new Page('Home', 1); <-- initialize the page object
$page->addJS('path/tojs.js'); <-- add javascripts if needed
$page->addCSS('path/tocss.css') <-- add css if needed
$page->startBody(); <--- start the page body
?>
--HTML HERE--
<?php
$page->endBody(); <--- close the body
echo $page->render('inc/template.php'); <-- render the template
------------------------------------------------------------------------------------------------
**/
class Page {
private $title, $id = 0, $stylesheets=array(), $javascripts=array(), $body;
function __construct($title, $id = 0) {
$this->title = $title;
$this->id = (int)$id;
}
function setTitle($title) {
$this->title = $title;
}
function setId($id){
$this->id = (int)$id;
}
function addCSS($path) {
$this->stylesheets[] = $path;
}
function addJS($path) {
$this->javascripts[] = $path;
}
function startBody() {
ob_start();
}
function endBody() {
$this->body = ob_get_clean();
}
function render($path) {
ob_start();
require($path);
return ob_get_clean();
}
function activeMenu($id){
echo $this->id == $id ? 'active' : '' ;
}
function minifyCSS(){
$buffer = "";
foreach ($this->stylesheets as $css) {
$buffer .= file_get_contents($css);
}
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
$buffer = str_replace(': ', ':', $buffer);
$buffer = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $buffer);
return $buffer;
}
}
Then in the template:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><?php echo $this->title; ?></title>
<?php
foreach ($this->stylesheets as $stylesheet) {
echo '<link href="' . $stylesheet . '" rel="stylesheet" type="text/css" />' . PHP_EOL;
}
//or echo '<style>'.$this->minifyCSS().'</style>'; to get minimized css
?>
</head>
<body>
<nav>
Home
Other Page
</nav>
<?php echo $this->body; ?>
<?php
foreach ($this->javascripts as $javascript) {
echo '<script src="' . $javascript . '"></script>' . PHP_EOL;
}
?>
</body>
</html>
I have a problem with highlighting using php include.
Here's my navigation bar:
<?php
echo '
<link rel="stylesheet" href="css/index-css.css" type="text/css">
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<div class="container">
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/womsy/index.php">Womsy</a>
</div>
<ul class="nav navbar-nav">
<li <?php echo $active[1] ?>Home</li>
<li <?php echo $active[2] ?>Blog</li>
<li <?php echo $active[3] ?>Projects</li>
<li <?php echo $active[4] ?>Contact</li>
<li class="active">About</li>
</ul>
</div>
</nav>';
$active[$current] = "class=active";
?>
I made this with bootstrap, and am trying to highlight via this: http://webdevjunk.com/coding/css/17/php-menu-includes-with-css-style-to-highlight-active-page-link/
<?php
$current = 1;
include 'php/menu.php';
?>
This is what I use on the page, but it doesn't highlight, but when I change the class in the <li> it does work.
Can someone help me figure this out?
function setActive($pageName)
{
if (stripos($_SERVER['REQUEST_URI'], $pageName)) {
echo 'class="active"';
}
}
//$pageName will be home ,blog,projects and contacts
Declare page variable at the very top of each individual page.
Example: <? $page="home";?> goes at top of homepage and <? $page="blog";?> would go on top of blog page, etc.
For each list item in your menu add if statement with corresponding variable and active class.
Example: <ul><li class="<?if($page=="home"){?>active<?}?>"><b>Home</b></li><li class="<?if($page=="blog"){?>active<?}?>"><b>Blog</b></li></ul>
What this does is assign each page a variable. The variable is compared in the if statements in the nav bar to determine which li gets the active class.
I'm generating a list (some sort of appointment card for students) with PHP. I want to be able to save this as a PDF.
I've successfully tried some basic layout with PHP and DOMPDF.
When I try to save the following as a PDF it does not work.
<?php
session_start();
// User session check
if(!$_SESSION['email'])
{
header("Location: login.php");//redirect to login page to secure the welcome page without login access.
}
include("php/getCustomerEvents.php");
// get row id = student id
$id = $_GET[id];
// check user language
$lang = $_SESSION['lang'];
switch ($lang)
{
case 'en':
$lang_file = 'lang.en.php';
break;
//case 'fr':
//$lang_file = 'lang.fr.php';
//break;
case 'nl':
$lang_file = 'lang.nl.php';
break;
default:
$lang_file = 'lang.nl.php';
}
include_once 'lang/'.$lang_file;
// Debug code
//print_r($_SESSION);
//echo "----------------------------------------------------------------------->".$_SESSION['lang']." = taal <br>";
//echo "----------------------------------------------------------------------->".$_SESSION['name']." = naam <br>";
//echo "----------------------------------------------------------------------->".$_SESSION['resource']." = id <br>";
//Echo "----------------------------------------------------------------------->".$_SESSION['admin']." = admin <br>";
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="css/bootstrap-select.css">
<style type="text/css">
.bs-example{
margin: 20px;
}
/* Fix alignment issue of label on extra small devices in Bootstrap 3.2 */
.form-horizontal .control-label{
padding-top: 7px;
}
</style>
</head>
<body >
<!-- Main content -->
<section class="content" >
<!-- Your Page Content Here -->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php echo $lang['LBL_LIST_EVENTS']; ?></h3>
</div><!-- /.box-header -->
<div class="box-body">
<table id="instructors" class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th><?php echo $lang['LBL_LESSON']; ?></th>
<th><?php echo $lang['LBL_LOCATION']; ?></th>
<th><?php echo $lang['LBL_TITLE']; ?></th>
<th><?php echo $lang['LBL_EVENT_START']; ?></th>
<th><?php echo $lang['LBL_EVENT_END']; ?></th>
</tr>
</thead>
<tbody>
<?php customerevents($id); ?><!-- function from getCustomerEvents.php -->
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-success" ><span class="glyphicon glyphicon-print" aria-hidden="true"></span> PDF </button>
<button type="submit" class="btn btn-success" ><span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> MAIL </button>
</div><!-- /.box-footer -->
</div><!-- /.box -->
</div><!-- /.col -->
</div><!-- /.row -->
</section><!-- /.content -->
<!-- Main Footer -->
<footer class="main-footer">
<!-- To the right -->
<div class="pull-right hidden-xs">
</div>
<!-- Default to the left -->
<strong>Copyright © 2015 biqs it.</strong> All rights reserved.
</footer>
</body>
</html>
The code I use to generate the PDF:
<?php
require_once("../dompdf/dompdf_config.inc.php");
//$content = "../" . $_GET["content"];
//$file_name = $_GET["file_name"];
$dompdf = new DOMPDF();
//$html = file_get_contents($content);
$html = file_get_contents('../pdf_customer_events.php');
$dompdf->load_html($html);
$dompdf->render();
$dompdf->stream("sample.pdf");
?>
What am i doing wrong? Or is DOMPDF not the right solution?
Printing raw file
To convert a file that does not contain any dependancy, you can get the content and give it to the convertion library.
$html = file_get_contents('pregenerated.html');
This method does not allow to pass variables that can be needed (session/POST...).
Printing advanced raw file
By bufferizing the content, you avoid to send it to the browser, it can then be given to the library.
ob_start();
include('content.php');
$html = ob_get_clean();
This way you can transmit session/post/get like you would normally do, and you can even handle errors correctly. You can also use templating engine for advanced output.
The main problem of ressources
By including the php script, all sub files (scripts, css, iframes, ...) are not included. So for simple pdf that does not include image, you need to get everything in one page.
Quite not maintenable ... but feasable.
Handling ressources easily
So, fortunatly there is some php tools that do interpret the page and can fetch any sub files. The most common is wkhtmltopdf, which is a binary that include Chrome's rendering engine webkit to interpret the page and print the pdf.
And for that, you can give him the content like the previous example, or give an url. You can control the printing (margins, colors ...).
It have many php wrappers to make it easy to use in your code.
Going further
But (there is always a but...) wkhtmltopdf does not use a recent engine of webkit, which can be annoying if like in my company you enjoy slick css3 and javascript canvas features.
What we made was to use headless browser, to render the page as a browser and print it in pdf (which is already what does wkhtmltopdf with great optimisations and features).
The most advanced headless browser is probably PhantomJS. Based on Webkit, it can print in many formats easily.
And it have a PHP wrapper: http://jonnnnyw.github.io/php-phantomjs/
var webPage = require('webpage');
var page = webPage.create();
page.viewportSize = { width: 1920, height: 1080 };
page.open("http://www.google.com", function start(status) {
page.render('google_home.jpeg', {format: 'jpeg', quality: '100'});
phantom.exit();
});
Side note:
In our company we use SlimerJS because it offers better output back in the days we build the service, this is only a concern because our pages were not made to be consistent accross browsers and the conversion messed up some part...
When we developed the service, SlimerJS did not provide full PDF printing support until 0.10 release that was in developement. So we had to compile it ourself with latest xulrunner.
Thanks to #Cyrbil I came to the working code below. Still having a problem with the CSS which causes the PDF to fail. From what I've found it has something to do with the bootstrap.css. Already tried to remove *before and after but still no PDF render. But I probably should post this as a new question.
<?php
session_start();
require_once("dompdf/dompdf_config.inc.php");
// User session check
// if(!$_SESSION['email'])
// {
// header("Location: login.php");//redirect to login page to secure the welcome page without login access.
// }
include("php/getCustomerEvents.php");
// get row id = student id
$id = $_GET["id"];
//check user language
$lang = $_SESSION['lang'];
switch ($lang)
{
case 'en':
$lang_file = 'lang.en.php';
break;
case 'fr':
$lang_file = 'lang.fr.php';
break;
case 'nl':
$lang_file = 'lang.nl.php';
break;
default:
$lang_file = 'lang.nl.php';
}
include_once 'lang/'.$lang_file;
ob_start(); // start output buffer
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<!--link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" /-->
<link href="css/biqs_print_bootstrap.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="css/bootstrap-select.css">
<style type="text/css">
.bs-example{
margin: 20px;
}
/* Fix alignment issue of label on extra small devices in Bootstrap 3.2 */
.form-horizontal .control-label{
padding-top: 7px;
}
tbody:before, tbody:after { display: none; }
</style>
</head>
<body >
<!-- Main content -->
<section class="content" >
<!-- Your Page Content Here -->
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header">
<h3 class="box-title"><?php echo $lang['LBL_LIST_EVENTS']; ?></h3>
</div><!-- /.box-header -->
<div class="box-body">
<table id="instructors" class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th><?php echo $lang['LBL_LESSON']; ?></th>
<th><?php echo $lang['LBL_LOCATION']; ?></th>
<th><?php echo $lang['LBL_TITLE']; ?></th>
<th><?php echo $lang['LBL_EVENT_START']; ?></th>
<th><?php echo $lang['LBL_EVENT_END']; ?></th>
</tr>
</thead>
<tbody>
<?php customerevents($id); ?><!-- function from getCustomerEvents.php -->
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
</div><!-- /.box-footer -->
</div><!-- /.box -->
</div><!-- /.col -->
</div><!-- /.row -->
</section><!-- /.content -->
<!-- Main Footer -->
<footer class="main-footer">
<!-- To the right -->
<div class="pull-right hidden-xs">
</div>
<!-- Default to the left -->
<strong>Copyright © 2015 biqs it.</strong> All rights reserved.
</footer>
</body>
</html>
<?php
$html = ob_get_contents();
ob_end_clean();
$dompdf = new DOMPDF();
$dompdf->load_html($html);
$dompdf->render();
$dompdf->stream("sample.pdf");
echo $html;
?>