Quantcast
Channel: phpGrid – PHP Datagrid
Viewing all 107 articles
Browse latest View live

Database Content Administration Application in 15 Lines of PHP Code

$
0
0
db-admin-demo

The source code of this tutorial is publicly available on Github.

Introduction

We will learn how to build a fully functional, single-page database content administration application using phpGrid and other PHP components with a minimum amount of code. The application will perform common data operations such as Create, Read, Update, Delete, otherwise known as CRUD on MySQL database tables.

Note the demo application requires phpGrid version 7 and above. The demo uses MySQL, however, the same basic code should work with other databases with the use of a different SQL schema SELECT statement.

Design

Our application will have a list of database schemas and tables on the left side – the sidebar – and a database table on the main screen – the main. Both the sidebar and the main are datagrids. On the main datagrid, which contains the database table, we will also add a search bar so users can search within the displayed grid.

Our design mockup:

db-admin-mockup

2-Column Layout

Let’s start by creating the layout. What we need is a fixed-width sidebar on the left while the main – a grid – stays “fluid” so it fills the remaining document width. The main grid will be populated with data from the database table selected from the left sidebar.

Luckily, CSSPortal has an excellent layout tool which easily generates a column-based layout with only point and click.

http://www.cssportal.com/layout-generator/

An alternative is to download this boilerplate (File -> Save As) which contains all the HTML and CSS code needed for this demo application.

Setup

Let’s start coding. Presumably, you have already installed phpGrid on your web server. If not, follow this guide to learn how – http://phpgrid.com/documentation/installation/

First, add the following lines to the TOP of our page

1
2
use phpGrid\C_DataGrid;
require_once("phpGrid/conf.php");

The first line adds the phpGrid namespace so PHP knows where to find phpGrid in the system. Otherwise, PHP will throw a nasty error – “Fatal error: Class ‘C_DataGrid’ not found”.

The second line references phpGrid by including its conf.php. The Installation Guide – http://phpgrid.com/documentation/installation/ – explains this in greater length.

Sidebar

The left sidebar contains a list of the tables found in each respective database in a subgrid.

Sidebar – Step 1

The first step is to return a list of current schemata from the selected database. In MySQL, the following SQL statement retrieves a list of schema names.

1
SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA

The PHP code to return a list of schemas is as follows:

1
2
3
4
// schema list
$dbs = new C_DataGrid("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA", "SCHEMA_NAME", "INFORMATION_SCHEMA.SCHEMATA");
$dbs->set_dimension('300px');
$dbs->set_pagesize(999)->set_scroll(true);

How the above code works:

set_dimension sets the width of the left sidebar to 300 pixels.
set_pagesize sets the height of the page to a very large number, e.g. 999. Thus, all data will be displayed on a single page. set_scroll removes the pagination controls normally found in the bottom footer.

Sidebar – Step 2

The second step displays a list of available database tables in each schema in a subgrid.

The PHP code to return a list of tables appears below.

1
2
3
4
// table list    $tbl = new C_DataGrid("SELECT TABLE_NAME, TABLE_SCHEMA, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES", "TABLE_NAME", "INFORMATION_SCHEMA.TABLES");
$tbl->set_col_hidden('TABLE_SCHEMA');
$tbl->set_pagesize(999)->set_scroll(true);
$tbl -> set_col_dynalink("TABLE_NAME", "db_admin.php", array("TABLE_NAME", "TABLE_SCHEMA"), '', "_top");

How the above code works:

First, we hide the TABLE_SCHEMA column because it is redundant. The page size is set to a large number (999) and scroll is set to true. Finally, and  most importantly, set_col_dynalink forms a dynamic URL for each database table used to populate the main datagrid.  You can learn more about the set_col_dynalink function here: http://phpgrid.com/documentation/set_col_dynalink/

Sidebar – Step 3

Lastly, set the subgrid. The subgrid displays an inline detail grid for each row in the parent grid. If you are not familiar with phpGrid subgrids, check out the subgrid demo online – http://phpgrid.com/example/subgrid/.

1
2
$dbs->set_subgrid($tbl, 'TABLE_SCHEMA', 'SCHEMA_NAME');
$dbs->display();

db-admin-sidebar

Main Column

The main column contains the datagrid for the database table. Recall that in the code to create the sidebar, Step 2, we used a function called “set_col_dynalink” which set a dynamic URL for every database table name in the URL query string. Now we need to retrieve the schema name and table name by using the following code:

1
2
$schemaName = (isset($_GET['TABLE_SCHEMA']) && isset($_GET['TABLE_SCHEMA']) !== '') ? $_GET['TABLE_SCHEMA'] : 'sampledb';
$tableName = (isset($_GET['TABLE_NAME']) && isset($_GET['TABLE_NAME']) !== '') ? $_GET['TABLE_NAME'] : 'orders';

The first line of code gets the schema name and the second gets the table name. There’s nothing special about this except we set a default value for each variable to be used in cases where the parameters are missing – such as as when the page is first loaded.

Below is the code for the main grid:

1
2
3
4
5
6
7
8
9
$dg = new C_DataGrid("SELECT * FROM $tableName",'orderNumber', "$tableName",
array("hostname"=>"localhost",
"username"=>"root",
"password"=>"",
"dbname"=>$schemaName,
"dbtype"=>"mysql",
"dbcharset"=>"utf8"));
$dg->enable_global_search(true);
$dg -> display();

How the above code works:

The first line uses phpGrid’s multiple database reference feature. This is essential because we need to reference different tables found in different databases. See http://phpgrid.com/example/multiple-databases-support/ for more information about how phpGrid can be configured to work with multiple databases.

Note that it is important to use the correct corresponding primary key when referencing the default database table.  In this case, we are referencing the “orders” table with the primary key “orderNumber”.

enable_global_search adds the global search bar to top of the grid. Finally, the last line displays our datagrid.

db-admin-main

That’s all there is to it! You now have a web-based database content management console using fewer than 15 lines of code.

But Wait, There’s More!

We can beef up the grid and take advantage of the fluid layout design by adding a few more lines of code.

First, we add a caption to show the current schema and table name. Then, we set the auto width, enable edit and then add a global search to the top.

1
2
3
4
5
$dg->set_caption(strtoupper("$schemaName.$tableName"));
$dg->enable_autowidth(true);
$dg->enable_edit();
$dg->set_scroll(true);
$dg->enable_global_search(true);

Finally, before we go, let’s add the following javascript event to make sure that the grid will only resize in its container and not in the browser window itself.

1
2
3
4
// set grid width to parent DIV
$dg->before_script_end .= 'setTimeout(function(){$(window).bind("resize", function() {
phpGrid_'
. $tableName .'.setGridWidth($(".right").width());
}).trigger("resize");}, 0)'
;

Summary

Congrats! You have just built a content management console for your database!

The source code of this tutorial is publicly available on Github.

The post Database Content Administration Application in 15 Lines of PHP Code appeared first on phpGrid.


redirect_after_submit()

$
0
0
  • Parameter(s):
    • $url: Redirect URL
  • Description:
    • Redirect form after submit.
  • Remarks:
    • It does not validate whether the submit is successful.
  • Example:
1
$dg -> redirect_after_submit('http://php.net')

The post redirect_after_submit() appeared first on phpGrid.

load_form()

$
0
0

* Paid version only.  Supported from version 7.0 and above.

  • Parameter(s):
    • $key: A database table primary key value.
  • Description:
    • Load an existing record from DB and display in edit form without the datagrid. The form will remain on the screen after submit.
  • Remark:
  • Example:
1
$dg -> enable_edit('FORM') -> form_only() -> load_form(8888);

The post load_form() appeared first on phpGrid.

Set Start Day of the Week in Datepicker

$
0
0
start-day-week-datepicker

Sunday was named as the first day in Jewish and early Christian tradition. However, Sunday is not always the first day of the week. In fact, some years ago, the International Organization for Standardization specified Monday as the first day. North American continue to follow Sunday as the first day of the week, while Europeans consider Monday the first day. Believe it or not, some countries have Saturday as the first day and some have no weeks (e.g. Africa)! Just see the start day of the week map below.

 

start-day-week

 

OK, enough of history. How do we actually go about changing the start day in our datepicker? Fear not, it is easier than you think. Just copy and paste the following event handling code in your phpGrid. It will change the default start day of the week from Sunday to Monday.

 
1
2
3
4
5
6
7
// change week start day to Monday
$weekStartDay = <<<DATEPICKWEEKSTARTDAY
function(){
    $('.hasDatepicker').datepicker('option', 'firstDay', 1)
}
DATEPICKWEEKSTARTDAY
;
$dg->add_event("jqGridAddEditAfterShowForm", $weekStartDay);

See Live Demo!

The post Set Start Day of the Week in Datepicker appeared first on phpGrid.

Enhance Edit Form

$
0
0
phpgrid-form-only-load

There are many ways to enhance the edit form in regular datagrid + form, or just in form-only mode. In version 7.0, there are two new functions at your disposal, add_form_group_header() and add_form_tooltip(). Each provides a simple way to include additional text to annotate the form.

In form only mode, the form will remain on the screen after each submit.

1
2
3
4
$dg->enable_edit('FORM')->form_only()
  ->add_form_group_header('employeeNumber', 'Employee Details')
  ->add_form_group_header('email', 'Other Info')
  ->add_form_tooltip('email', 'Got mail?');

Live demo!

The post Enhance Edit Form appeared first on phpGrid.

Rating Plugin Integration

$
0
0
datagrid rating

phpGrid has built-in jQuery rating plugin support since version 7.1.5. In set_col_format(), simply use “rating” as the format type. The value must be an integer from 1 to 5.

1
2
3
4
$dg = new C_DataGrid("SELECT id, Contact_Last, Title, Company, Rating, Email FROM contact", "id", "contact");
$dg->set_col_format('Rating', 'rating');
$dg->set_dimension(800);
$dg -> display();

See Live Demo!

The post Rating Plugin Integration appeared first on phpGrid.

Bulk Edit, Select Multiple Rows

$
0
0
bulk-edit2

You can select multiple records with set_multiselect() method. When multiselect is enabled, a checkbox is shown to the left of each row. Use multiselect feature to for bulk edit such as delete multiple records and save multiple selected rows.

Version 6.7.10 Update

Set the 2nd parameter in set_multiselect() to true to persist row selection following pagination. Before the selection is lost after going to another page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$dg = new C_DataGrid("SELECT * FROM Orders", "orderNumber", "Orders");

// change column titles
$dg -> set_col_title("orderNumber", "Order No.");
$dg -> set_col_title("orderDate", "Order Date");
$dg -> set_col_title("shippedDate", "Shipped Date");
$dg -> set_col_title("customerNumber", "Customer No.");
 
// enable edit
$dg -> enable_edit("INLINE", "CRUD");

// hide a column
$dg -> set_col_hidden("requiredDate");

// read only columns, one or more columns delimited by comma
$dg -> set_col_readonly("orderDate, customerNumber");

// required fields
$dg -> set_col_required("orderNumber, customerNumber");

// multiple selection. The 2nd true signals grid not lose selections following pagination
$dg -> set_multiselect(true, true);
 
$dg -> display();

Bonus: send selected rows back to server

We can also easily obtain the selected row information and send captured rows back to server side for additional processing via AJAX. Below we got some working code snippets so you can get jump started. Check out the live example to see them in action!

Retrieve selected rows (Javascript)

1
2
3
4
5
function ShowSelectedRows(){
    var rows = getSelRows();
    // replace your own javascript here
    alert(rows);
}

Retrieve selected row ids and posted to a remote URL via $.ajax in JSON format (Javascript)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function saveSelectedRowIds() {
    var rows = getSelRows();
    if (rows == "") {
        alert("no rows selected");
        return;
    } else {
        $.ajax({
          url: 'http://example.com/save_selected_rowids.php',
          data: {selectedRows: rows},
          type: 'POST',
          dataType: 'JSON'
        });
        alert(rows + ' row Ids were posted to a remote URL via $.ajax');
    }
    // window.location = "index.php#ajax/save_selected_row.php?refresh=1&rows="+rows;
}

Retrieve selected rows objects and posted to a remote URL via $.ajax in JSON format (Javascript)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function saveSelectedRows(){
    gdata = $('#orders').jqGrid('getRowData');
    rows = getSelRows();
    if (rows == "") {
        alert("no rows selected");
        return;
    } else {
        selIndices = [];  // get index selected
        $.each(gdata, function(index, value){
            if($.inArray(value["orderNumber"], rows) != -1){
                selIndices.push(index);
            }
        });
        selRows = [];   // get row object from each index selected
        $.each(gdata, function(index, value){
            if($.inArray(index, selIndices) != -1){
                selRows.push(gdata[index]);
            }
        })
        $.ajax({
          url: 'http://example.com/save_selected_rows.php',
          data: {selectedRows: selRows},
          type: 'POST',
          dataType: 'JSON'
        });
        alert(selRows + ' with row ids ' + rows + ' were posted to a remote URL via $.ajax');
    }
}

To get value from a different cell of the select row:

1
$('#TABLE_NAME').jqGrid('getCell',row_id,'COLUMN NAME');

See Live Example!

The post Bulk Edit, Select Multiple Rows appeared first on phpGrid.

Drag & Drop Rows Between Grids

$
0
0

dnd-phpgrid

You can drag and drop rows between two or more grids using a mouse.

In the demo, we have both orders and employees datagrids on the same page.

1
2
3
$dg = new C_DataGrid("select * from employees", "employeeNumber", "employees");
$dg->enable_edit("FORM", "CRUD");
$dg->display();

We add the following Javascript to enable drag and drop between the two grids.

The Ondrop event posts the row data to another url “save_dropped_row.php”. You must implement this server side script to handle how you would like the row data to be saved.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
$(function(){
  jQuery("#orders").jqGrid("sortableRows", {});
  jQuery("#employees").jqGrid("sortableRows", {});

  jQuery("#orders").jqGrid('gridDnD',{
    connectWith:'#employees',
    drop_opts:{
      hoverClass: "ui-state-active",
    },
    ondrop: function(evt, obj, data){
      $.ajax({
          method: "POST",
          url: "save_dropped_row.php",
          data: data,
        }).done(function( msg ) {
            console.log( "Data Saved: " + msg );
        })
    },

  });  
})
</script>

Complete Drag and drog API documentation can be found on jQuery UI draggable and droppable widgets.

Run Live Demo!

The post Drag & Drop Rows Between Grids appeared first on phpGrid.


Show Remaining Characters in Textarea/Input

$
0
0
input char counter

In a recent user support request, the user would like to see the remaining characters allowed for data input in a text input. This is not a phpGrid standard feature. How can it be achieved?

Custom event comes to rescue!

First of all, we must insert a new html node for our counter right after the text input. In our demo, we use the “status” field. The new counter will display the text of remaining allowed characters for data entry.

1
<span id='counter'></span>

We bind a new “onkeyup” JavaScript event to the “status” text input. The phpGrid event you should use is “jqGridAddEditAfterShowForm” so that the counter is only displayed AFTER the form is shown.

1
2
3
4
5
6
7
8
$afterShowForm = <<<AFTERSHOWFORM
function ()
{
    $("#tr_status > td.CaptionTD + td.DataTD").append("<span id='counter'></span>");   
    $("#status").attr("onkeyup","updateCounter()");
}
AFTERSHOWFORM
;
$dg->add_event('jqGridAddEditAfterShowForm', $afterShowForm);

We use the CSS selector to style our counter. Most importantly, we make sure it is displayed in the right place (at the end of the text input box).

1
2
3
4
5
6
7
8
9
/* move the counter atop */
#counter{
    font-size: 8px;
    position: relative;
    top: -15px;
    float: right;
    padding-right: 25px;
    display:inline-block;
}

Lastly, insert the javascript function below that updates our counter during each key press.

1
2
3
4
5
6
7
8
// show how much characters in "status" field input. Max is 10
function updateCounter() {
  var maxChar = 10;
  var pCount = 0;
  var pVal = $("#tr_status > td.CaptionTD + td.DataTD  input").val();
  pCount = pVal.length;
  $("#counter").text(pCount + '/' + maxChar);
}

Run Live Demo! (Click “Status” input box, and start typing)

The post Show Remaining Characters in Textarea/Input appeared first on phpGrid.

Build a Simple CRM from Start to Finish

$
0
0

Customer Relationship Management (CRM) is a system that manages customer interactions and data throughout the customer lifecycle between the customer and the company across different channels. In this tutorial, we are going to build a custom CRM in PHP, which a sales team can use to track customers through the entire sales cycle.

We’ll be creating a simple CRM system for salespeople to:

  • Access their tasks
  • View their leads
  • Create new tasks for each lead
  • Create new opportunity
  • Lose a sale

Sales managers will be able to:

  • Manage all customers
  • Manage sales team
  • View current sales activities
Download Source Code

Building Blocks of a CRM

Here is a list of the essential components of the CRM:

  • Leads: initial contacts
  • Accounts: Information about the companies you do business with
  • Contact: Information about the people you know and work with. Usually, one account has many contacts
  • Opportunities: Qualified leads
  • Activities: Tasks, meetings, phone calls, emails and any other activities that allow you to interact with customers
  • Sales: Your sales team
  • Dashboard: CRM dashboards are much more than just eye candy. They should deliver key information at a glance and provide links to drill down for more details.
  • Login: Salespeople and managers have different roles in the system. Managers have access to reports and sales pipeline information.
Sales Process Overview

System Requirements

  • PHP 5.3+,
  • MySQL or MariaDB
  • phpGrid

Create CRM Database

We will start by creating our custom CRM database. The main tables we will be using are:

  • contact – contains basic customer data
  • notes – holds information collection from Contact by sales people.
  • users – information about sales people
Main Database Tables

The contact table contains basic customer information including names, company addresses, project information, etc.

The notes table is used to store all sales activity information such as meetings and phone calls.

The users table holds login information about users of the system such as usernames and passwords. Users can also have roles, either Sales or Manager.

All other tables are simple lookup tables to join to the aforementioned three main relational database tables.

  • contact_status – contains contact status such as Lead and Opportunity each indicating a different stage in a typical sales cycle
  • task_status – the task status can be either Pending or Completed
  • user_status – a sale person can be Active or Inactive
  • todo_type – a type of task either Task or Meeting
  • todo_desc – description of a task such as Follow Up Email, Phone Call, and Conference etc.
  • roles – a user can be either a Sales Rep or a Manager

Complete Database Schema Diagram

A database schema is the structure that represents the logical view (tables, views, primary and foreign keys) of the entire database. A database schema includes entities and the relationship among them.

It is a good practice to have one primary key for each table in a relational database. A primary key is a unique identifier for each record. It can be the social security number (SSN), vehicle identification number (VIN), or simply auto-increment number (a unique number that is generated when a new record is inserted into a table).

Below is the database diagram of our simple CRM. The key symbol in each table represents the table primary key. The magnifying glass indicates foreign key linking another table in the database. Sometimes we call it the “lookup” table.

install.sql

Once you have an understanding of the database table structure, find the `install.sql` script in the db folder and use a MySQL tool such as MySQL Workbench or Sequel Pro to run the SQL script. It should create a new relational database named custom_crm and its database tables.

Setup phpGrid

Our simple CRM contains many datagrids. The datagrid is a spreadsheet-like data table that displays rows and columns representing records and fields from the database table. The datagrid gives the end-user ability to read and write to database tables on a web page.

We opt-in a datagrid tool from phpGrid to create the datagrid. The reason to use a tool instead of building them from scratch is that developing the datagrid is usually extremely tedious and error-prone. The datagrid library will handle all internal database CRUD (Create, Remove, Update, and Delete) operations for us with better and faster results with little code.

To install phpGrid, follow these steps:

  1. Unzip the phpGrid download file
  2. Upload the phpGrid folder to the `phpGrid` folder
  3. Complete the installation by configuring the `conf.php` file

Before we begin coding, we must specify the database information in `conf.php`, the phpGrid configuration file. Here is an example of database connection settings:

1
2
3
4
5
6
define('PHPGRID_DB_HOSTNAME', 'localhost');
define('PHPGRID_DB_USERNAME', 'root');    
define('PHPGRID_DB_PASSWORD', '');
define('PHPGRID_DB_NAME', 'custom_crm');
define('PHPGRID_DB_TYPE', 'mysql');  
define('PHPGRID_DB_CHARSET','utf8');
  • PHPGRID_DB_HOSTNAME – web server IP or host name
  • PHPGRID_DB_USERNAME – database user name
  • PHPGRID_DB_PASSWORD – database password
  • PHPGRID_DB_NAME – database name of our CRM
  • PHPGRID_DB_TYPE – type of database
  • PHPGRID_DB_CHARSET – always ‘utf8’ in MySQL

Page Template

The CRM Page Template

Before we can start building our first page of the CRM, it is a good practice to make the page items reusable such as header and footer.

The page will be comprised of a header, menu, body and footer. We will start by creating a reusable page template.

head.php

This is a basic HTML5 template header. It includes a link to a custom stylesheet that will be created in a later step.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html lang="en">

<head>
  <title>My Custom CRM</title>
  <meta charset="utf-8">
  <link rel="stylesheet" href="../css/style.css">
</head>

<body></code>
</html>

<h4>menu.php</h4>

<figure id="post-251806" class="align-none media-251806"><img src="https://raw.githubusercontent.com/phpcontrols/phpgrid-custom-crm/master/design/menus/custom-crm-salesrep-menu.png" alt="" /><figcaption>The Top Menu Bar</figcaption></figure>



[cc lang="html"]
<div id="menu">
    <ul>
        <li><a href="tasks.php" <?php if($_GET['currentPage'] == 'tasks') echo 'class="active"'; ?>>Tasks</a></li>
        <li><a href="leads.php" <?php if($_GET['currentPage'] == 'leads') echo 'class="active"'; ?>>Leads</a></li>
        <li><a href="opportunities.php" <?php if($_GET['currentPage'] == 'opportunities') echo 'class="active"'; ?>>Opportunities</a></li>
        <li><a href="customerwon.php" <?php if($_GET['currentPage'] == 'customerwon') echo 'class="active"'; ?>>Customers/Won</a></li>
    </ul>
</div></code>

Notice the usage of

1
$_GET['currentPage']

Each page will set a value which will highlight the name of the current page on the top menu bar.

Include the following code in `style.css` for menu styling. It will transform the above, unordered list into a menu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#menu ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #1590C2;
}
#menu ul li {
  float: left;
}
#menu ul li a {
  display: block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}
#menu ul li a:hover,
#menu .active {
  background-color: #ddd;
  color: black;
}</code>

footer.php

Closing tags for the elements we opened in the header:

1
2
</body>
</html>

Our Complete Reusable Page Template

This is the complete page template. The main content will go after Section Title.

1
2
  include_once("../phpGrid/conf.php");      
  include_once('../inc/head.php');
1
2
3
4
5
6
7
8
9
10
11
<h1>My Custom CRM</h1>

<?php include_once('../inc/menu.php'); ?>

<h3>Section Title</h3>

<?php
  // Your main content, such as a datagrid, goes here
?>

<?php include_once('../inc/footer.php'); ?>

CRM Main Pages

Are you still with me? Good! We can now finally develop the first page in our CRM.

Our CRM for sales team members has four pages:

  • Tasks
  • Leads
  • Opportunities
  • Customers/Won

Each page indicates a different stage in a typical sales cycle.

Design Mockup

Here’s our CRM design mockup for the sales people.

Sales Team CRM Screen

Tasks

When a sales team member logged in, the first page he sees is a list of current tasks.

As you may recall, our notes table holds all the sales activity information. We can create a datagrid and populate it from the Notes table using phpGrid.

The Tasks page main content is a datagrid. The following two lines will give us a list of tasks of the current sales person.

1
2
3
  $dg = new C_DataGrid("SELECT * FROM notes", "ID", "notes");
  $dg -> display();
?>
  • The first line creates a phpGrid object by passing the SELECT SQL statement, its primary key – ID, and then the name of the database table – notes.
  • The second and the final line calls display() function to render the datagrid on the screen. Check out the basic datagrid demo for more detail.

Leads

The leads page contains list of current leads that the sales person is responsible for. Each Lead can have one or many Notes. We will use the phpGrid subgrid feature for that.

We also need to use set_query_filter() to display only the leads, Status = 1, and only for the current sales person.

Contact status table

Contact Status Table
1
2
3
4
5
6
7
8
9
10
  $dg = new C_DataGrid("SELECT * FROM contact", "id", "contact");
  $dg->set_query_filter(" Status = 1 && sales_rep = 1 ");

  // the detail grid displays notes about a lead
  $sdg = new C_DataGrid("SELECT * FROM notes", "id", "notes");
  $sdg->set_query_filter(" Sales_Rep = 1 ");
  $sdg->enable_edit();

  $dg->set_subgrid($sdg, 'Contact', 'id');
  $dg -> display();

Opportunities

A Lead becomes an Opportunity once it is qualified. The Opportunities page is similar to the Leads page. The only difference is the filtered status code in set_query_filter is Status = 2.

1
2
3
4
5
6
7
8
9
  $dg = new C_DataGrid("SELECT * FROM contact", "id", "contact");
  $dg->set_query_filter(" Status = 2 && sales_rep = 1 ");

  $sdg = new C_DataGrid("SELECT * FROM notes", "id", "notes");
  $sdg->set_query_filter(" Sales_Rep = 1 ");
  $sdg->enable_edit();

  $dg->set_subgrid($sdg, 'Contact', 'id');
  $dg -> display();

Customers/Won

Customers/Won has the Status = 3. Similar to Leads and Opportunities, Customers/Won can also have Notes.

1
2
3
4
5
6
7
8
9
  $dg = new C_DataGrid("SELECT * FROM contact", "id", "contact");
  $dg->set_query_filter(" Status = 3 && sales_rep = 1 ");

  $sdg = new C_DataGrid("SELECT * FROM notes", "id", "notes");
  $sdg->set_query_filter(" Sales_Rep = 1 ");
  $sdg->enable_edit();

  $dg->set_subgrid($sdg, 'Contact', 'id');
  $dg -> display();

That’s all there is to it for sales people in our simple CRM.

Manager Dashboard

The sales manager will have access to all records in the sales pipeline as well as the ability to manage sales team and customer data.

Here’s the design mockups:

My Sales Reps

Menu

Managers Dashboard has three menu items.

1
2
3
4
5
6
7
<div id="menu">
    <ul>
        <li><a href="?gn=users" <?php if($tableName == 'users') echo 'class="active"'; ?>>My Sales Reps</a></li>
        <li><a href="?gn=notes" <?php if($tableName  == 'notes') echo 'class="active"'; ?>>Tasks</a></li>
        <li><a href="?gn=contact" <?php if($tableName == 'contact') echo 'class="active"'; ?>>Contact</a></li>
    </ul>
</div>

Main content

Each menu item represents a table in the CRM database. $_GET[‘gn’] will store the table name. It dynamically generates the datagrid based on table name passed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  $tableName = (isset($_GET['gn']) && isset($_GET['gn']) !== '') ? $_GET['gn'] : 'users';

  switch($tableName){
    case "users":
        $dg = new C_DataGrid("SELECT * FROM users", "id", "users");

        $sdg = new C_DataGrid("SELECT * FROM contact", "id", "contact");
        $dg->set_subgrid($sdg, 'sales_rep', 'id');
        break;

    case "notes":
        $dg = new C_DataGrid("SELECT * FROM notes", "id", "notes");
        break;

    case "contact":
        $dg = new C_DataGrid("SELECT * FROM contact", "id", "contact");

        $sdg = new C_DataGrid("SELECT * FROM notes", "id", "notes");
        $sdg->enable_edit();

        $dg->set_subgrid($sdg, 'Contact', 'id');
        break;
}

  $dg->enable_edit();
  $dg->display();
?>

My Sales Rep

Since a sales manager needs to quickly find out whom a sale person is working with, we added a detail grid $sdg populated from contact table and link with the parent grid.

1
2
$sdg = new C_DataGrid("SELECT * FROM contact", "id", "contact");
$dg->set_subgrid($sdg, 'sales_rep', 'id');

sales_rep is the connecting key in contact table to the id that is the foreign key in users table. Remember the users stores all of our sales people information.

Screenshots

CRM – Sales Screen
CRM – Manager Screen

Interactive Demo

Login as Sales Rep Login as Manager

GitHub Source Code

Download Source Code

The post Build a Simple CRM from Start to Finish appeared first on phpGrid.

Build a Project Management Application From Scratch

$
0
0
Download Demo Source Code

What is a Project Management Application?

A project management application is a software system used for project planning, resource allocation, tracking of project components, and change management.

What is in a Project Management Application?

We will be creating a simple and easily customizable PM system to tracks projects, including milestones, tasks, hours, costs, and more. Since every project is unique, this tutorial merely means to build an application foundation; you should be able to easily extend it based on your requirements.

In our project management application, employees will be able to:

  • View their tasks

  • Log in hours worked

Managers will be able to:

  • Manage projects

  • Manage milestones

  • Manage tasks

  • Manage costs and hours

  • Manage employee resources

The Building Blocks of a Project Management System

Here are the primary functions of a project management system:

  • Project planning: To define a project schedule, a project manager may use the software to map project tasks and visually describe task interactions.

  • Task management: Allows the project manager to create and assign tasks, establish deadlines, and produce status reports.

  • Resource management: Defines responsibilities – who is supposed to do what.

  • Budgeting and cost tracking: A good project management application facilitates budget reporting as well as viewing, notifying, and updating costs for stakeholders.

  • Time tracking: The software must have the ability to track time spent on all tasks and maintain records for third-party consultants.

enter image description here

System Requirements

  • PHP 5.3+

  • MySQL or MariaDB

  • phpGrid

Creating a Project Management Database

We will start by creating our project management database. The main tables we will use are:

  • Clients – customer company data

  • Contacts – client contact data. A client can have one or more contacts.

  • Projects – project information

  • Milestones – project milestone

  • Tasks – project tasks

  • Hours – time spent on each task

  • Costs – cost of a task

  • Users – user data; one can be either an employee or a manager

enter image description here

Other tables (lookup tables):

  • ms_status –

  • proj_status –

  • task_status –

Complete Database Schema Diagram

A database schema is the structure that represents the logical view of the entire database: tables, views, and primary and foreign keys. A database schema includes all entities and the relationships between them.

Below is the database diagram of our simple project management application. The key symbol in each table represents the table’s primary key while the magnifying glass indicates a foreign key linking it to another table (lookup table) in the database.

The diagram is made with DBSchema.

enter image description here

simple_pm_install.sql

Once you have an understanding of the database’s table structure, obtain the simple_pm_install.sql sql script from this tutorial’s GitHub repo, and then execute the sql script using a MySQL tool such as MySQL Workbench or Sequel Pro. This will create a new database named simple_pm and tables we need in this tutorial.

Setup phpGrid

Our simple project management contains many DataGrids. The DataGrid is a spreadsheet-like data table which displays rows and columns representing records and fields from the database table. The DataGrid provides the end-user with the ability to read and write to the database tables on a web page.

To create the DataGrid, we use a dataGrid tool from phpGrid . The reason why we use a tool instead of building our grids from scratch is that developing a DataGrid in php is usually extremely tedious and prone to errors. The phpGrid DataGrid library will handle all internal database CRUD (Create, Remove, Update, and Delete) operations for us offering faster and better results with minimal coding.

To install phpGrid, follow these steps:

  1. Unzip the phpGrid download file.
  2. Upload the phpGrid folder to the phpGrid folder.
  3. Complete the installation by configuring the conf.php file.

Before we begin coding, we must include the following information in “conf.php,” the phpGrid configuration file. Here is an example of the database connection settings:

1
2
3
4
5
6
define('PHPGRID_DB_HOSTNAME', 'localhost');
define('PHPGRID_DB_USERNAME', 'root');
define('PHPGRID_DB_PASSWORD', '');
define('PHPGRID_DB_NAME', 'custom_pm');
define('PHPGRID_DB_TYPE', 'mysql');
define('PHPGRID_DB_CHARSET','utf8');
  • PHPGRID_DB_HOSTNAME – web server IP or host name

  • PHPGRID_DB_USERNAME – database user name

  • PHPGRID_DB_PASSWORD – database password

  • PHPGRID_DB_NAME – database name

  • PHPGRID_DB_TYPE – type of database

  • PHPGRID_DB_CHARSET – always ‘utf8’ in MySQL

Page Template

enter image description here

Our page will be comprised of a header, menu, body, and footer. Instead of creating the same page elements repeatedly, we will start by creating a reusable page template.

head.php

This is a basic HTML5 template header; it includes a link to a custom stylesheet that will be created in a later step.

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>My Custom Project Management Application</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link type="text/css" rel="Stylesheet" href="../css/style.css" />
</head>
<body>
1
2
3
4
5
6
<div id="menu">
<ul>
<li><a href="clients.php" <?php if($_GET['currentPage'] == 'clients') echo 'class="active"'; ?>>Clients</a></li>
<li><a href="projects.php" <?php if($_GET['currentPage'] == 'projects') echo 'class="active"'; ?>>Projects</a></li>
</ul>
</div>

enter image description here

Notice the usage of $_GET[‘currentPage’]. Each page will set a value that will highlight the name of the current page on the top menu bar.

Include the following code in style.css for menu styling; it will transform the above unordered list into a menu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#menu ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #1590C2;
}

#menu ul li {
    float: left;
}

#menu ul li a {
    display: block;
    color: white;
    text-align: center;
    padding: 14px 16px;
    text-decoration: none;
}

#menu ul li a:hover,
#menu .active {
    background-color: #ddd;
    color:black;
}

footer.php

Simply includes the closing tags for the elements we opened in the header:

1
2
</body>
</html>

Our Complete Reusable Page Template

The main content will go after the section title.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include_once("../phpGrid/conf.php");
include_once('../inc/head.php');
?>

<h1>My Custom Project Management Application</h1>

<?php include_once('../inc/menu.php'); ?>

<h3>Section Title</h3>

<?php
// Your main content (datagrid eg.), such as a datagrid, goes here
?>

<?php include_once('../inc/footer.php'); ?>

Project Management Main Pages

Our project management application for managers has four pages:

  • Clients

  • Client Details

  • Projects

  • Project Details

The Clients page displays a list of clients with links to individual client details (Client Details page).

The Projects page displays a list of projects being managed with links to project details (Project Details page).

Design Mockup

Here is our project management application design mockup for project managers who manage one or more projects and assign tasks to employees.

enter image description here

Clients

When a manager logs in to the project management system, the first page he sees is the Clients page which contains a complete list of companies.

The following code will give us a list of clients.

1
2
3
4
$dgClient = new C_DataGrid("SELECT * FROM clients", "id", "clients");
$dgClient->set_col_dynalink("Name", "client-details.php", "id");
$dgClient->enable_edit();
$dgClient->display();
  • The first line creates a phpGrid object by passing the SELECT SQL statement with its primary key id followed by the name of the database table – clients.

  • The second line creates a dynamic URL from the primary key “id”; it uses a function called set_col_dynalink(). This function sets a specific column-to-display HTML hyperlink URL based on dynamic values. If the primary key “id” has the value 100, it will display a URL like this client-details.php?id=100 which drills down the client detail page.

  • The third line, enable_edit(), makes the DataGrid editable and all CRUD (Create, Read, Update, Delete) operations are now accessible.

  • The last line calls the display() function to render the DataGrid on the screen.

You can check out more demos below:

Client Details

From the Clients page, the client name has a hyperlink that redirects to the Client Details page for that client when clicked.

enter image description here

From the Client Details page, we need to obtain the Client ID that is passed as the URL parameter.

1
$clientId = (isset($_GET['id'])) ? intval($_GET['id']) : 0;

In our application, the Client ID should always be an integer. Thus, we use the PHP intval() function to ensure the Client ID is returned as an integer.

The following code displays projects associated with the current $clientId using the filter function set_query_filter(). In addition, we make the DataGrid editable with the enable_edit() function; phpGrid will take care of any CRUD operations for us.

Client Details > Projects

As you may notice, we again use the same function, set_col_dynalink(), to create hyperlinks to the Project Details table using the Project ID. We will get into the project-details.php page next.

1
2
3
4
5
6
7
8
9
<h4>Projects</h4>

<?php
$dgProj = new C_DataGrid("SELECT * FROM projects", "id", "projects");
$dgProj->set_query_filter(" ClientID = $clientId ");
$dgProj->set_col_dynalink("ProjectName", "project-details.php", "id");
$dgProj->enable_edit();
$dgProj->display();
?>
Client Details > Contacts

Under the Projects DataGrid, a list of contacts associated with the $clientid is displayed using the same functions set_query_filter() and enable_edit().

Contacts

1
2
3
4
5
6
<?php
$dgCont = new C_DataGrid("SELECT * FROM contacts", "id", "contacts");
$dgCont->set_query_filter(" ClientID = $clientId ");
$dgCont->enable_edit();
$dgCont->display();
?>

Projects

Now, let’s build the Projects page.

The Projects page displays a list of managed projects. It is very similar to the Clients page except that the database table is “Projects,” and the hyperlinks have the URL project-details.php instead of client-details.php.

1
2
3
4
5
6
<?php
$dgProj = new C_DataGrid("SELECT * Budget FROM projects", "id", "projects");
$dgProj->set_col_dynalink("ProjectName", "project-details.php", "id");
$dgProj->enable_edit();
$dgProj->display();
?>

Project Details

From the Projects page, each project name has a hyperlink which redirects to each individual Project Details page when clicked.

enter image description here

And from the Project Details page, we retrieve the Project ID for the URL parameter.

1
$projectId = (isset($_GET["id"])) ? intval($_GET["id"]) : 0;

Look familiar? It should because both Projects and Project Details pretty much follow the same coding pattern used in the Clients and Client Details pages; there are not really that many surprises.

The Project Details page is made of the following grids, all filtered by the $projectId obtained from the URL parameter.

  • Milestones

  • Tasks

  • Hours

  • Costs

Milestones

A milestone marks a major event in a project timeline. Here, we can easily display all the milestones of a project by filtering the value $projectId. Project managers have the necessary access rights to modify the milestones.

1
2
3
4
5
6
7
8
<h4>Milestones</h4>

<?php
$dgMS = new C_DataGrid("SELECT * FROM milestones", "id", "milestones");
$dgMS->set_query_filter(" ProjectID = $projectId ");
$dgMS->enable_edit();
$dgMS->display();
?>

Likewise, we can easily filter and display a list of tasks for the current project.

1
2
3
4
5
6
7
8
<h4>Tasks</h4>

<?php
$dgTask = new C_DataGrid("SELECT * FROM tasks", "id", "tasks");
$dgTask->set_query_filter(" ProjectID = $projectId ");
$dgTask->enable_edit();
$dgTask->display();
?>

I think you are probably getting the hang of it now. Here’s the code for the two remaining DataGrids.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<h4>Hours</h4>

<?php
$dgHour = new C_DataGrid("SELECT * FROM hours", "id", "hours");
$dgHour->set_query_filter(" ProjectID = $projectId ");
$dgHour->enable_edit();
$dgHour->display();
?>

<h4>Costs</h4>

<?php
$dgCost = new C_DataGrid("SELECT * FROM costs", "id", "costs");
$dgCost->set_query_filter(" ProjectID = $projectId ");
$dgCost->enable_edit();
$dgCost->display();
?>

Employees Page

We can now move on to the final part of the tutorial, the Employees page. Employees can login to view active project tasks assigned to them, track task hours, and costs. Their responsibility is simple: to monitor the tasks and log hours worked on any specific project task.

Design Mockup

enter image description here

The Employees page has only one menu item: Tasks.

enter image description here

My Active Tasks

The first part of the page shows a list of active tasks assigned to the current employee. Each task will have the hours reported by the current employee; this is a perfect situation in which to use a phpGrid subgrid.

We also need to use set_query_filter() to display only active tasks that have Status value “2”, and only for the current employee.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$empId = intval(2); // hard code for the demo. In real world, the id should be retrieved in PHP SESSION

// active (StatusID = 2) tasks datagrid for the current employee
$dgTask = new C_DataGrid("SELECT * FROM tasks", "id", "tasks");
$dgTask->set_query_filter(" EmployeeID = $empId AND StatusID = 2 "); // Active value is 2

// hours reported for the current employee
$dgHour = new C_DataGrid("SELECT * FROM hours", "id", "hours");
$dgHour->set_query_filter(" EmployeeID = $empId ");
$dgHour->enable_edit();

// hours datagrid is a subgrid of the tasks datagrid
$dgTask->set_subgrid($dgHour, "TaskID", "id");
$dgTask->display();
?>

For demo purposes, we hard-coded the Employee ID to 2. In a real-world application, the Employee ID value should be stored and retrieved using PHP SESSION.

We then create the active Tasks DataGrid for the current employee. Notice the filter function.

Once we’ve defined the grid for the active tasks, we create a DataGrid to log the hours reported by the current employee.

Lastly, set_subgrid() causes the Hours DataGrid to become a subgrid of the Tasks DataGrid. The linking field in the Hours subgrid is ‘TaskID’, which is the second parameter, and in the main grid Tasks, it is “id,” the third parameter.

1
$dgTask->set_subgrid($dgHour, "TaskID", "id");

enter image description here

My Hours History

Lastly, we would like to display a read-only DataGrid using data from the Hours table for the current employee for reviewing purposes.

1
2
3
4
5
6
<?php
$dgHourHist = new C_DataGrid("SELECT * FROM hours", "id", "hours");
$dgHourHist->set_jq_gridName("myHoursHistory"); // the grid name must be unique
$dgHourHist->set_query_filter(" EmployeeID = $empId ");
$dgHourHist->display();
?>

Notice we used a function called set_jq_gridName(). You can find more documentation here. This function sets a unique object name for the DataGrid. By default, phpGrid uses the database table name as its internal object name. Since we already created a DataGrid from the Hours table in the last part, we must set a unique name for our second Hours DataGrid.

Screenshots

Managers

enter image description here

enter image description here

Employee

enter image description here

Run Demo Download Demo Source Code

The post Build a Project Management Application From Scratch appeared first on phpGrid.

A Step-by-Step Guide to Building a Donation Manager from Scratch in PHP – Part I

$
0
0

Introduction

This Donations Manager application can be used by charitable organizations to manage the processing of donations as well as ensure accurate data entry and seamless communications with donors. In addition, we will include a donation summary report with charts in our application.

Download Complete Source Code

System Requirements

  • PHP 5.3+
  • MySQL or MariaDB
  • phpGrid
  • phpChart

Database Overview

Our Donation Manager system has four objects.

  • Donor – Personal information about the donor.
  • Donation – The amount donated for a particular campaign
  • Campaign – Donation campaign information
  • Organization – The organization that manages the donations

Our database is simple and straightforward. Each table is an entity that represents one of the above objects.

Programming Terminology – Object or Entity

An entity is a database term that’s typically represented by a table in a database schema.
An object is an object-oriental programming term often mapped to a database table.

In our data model, donations is used to store the information about donations; campaigns is used to compile campaign data and information about the campaign; the organization managing the campaign is stored in org.

enter image description here

Set up the Donation Manager Database

Obtain the donation_manager_db.sql SQL script from this tutorial’s GitHub repo, and then execute the SQL script using a MySQL tool such as MySQL Workbench or Sequel Pro. This will create a new database named donation_manager and the tables we will need in this tutorial.

Setup phpGrid

Our simple project management application contains many datagrids. A datagrid is a spreadsheet-like data table that displays rows and columns which representing records and fields stored in the database table. These grids provide the end-user with the ability to read and write to the database tables from a web page.

The phpGrid datagrid component handles all internal database CRUD (Create, Remove, Update, and Delete) operations for us, offering faster and better results with minimal coding.

Be sure to download a free copy of phpGrid before you proceed.

To install phpGrid, follow these steps:

  1. Unzip the phpGrid download file.
  2. Upload the phpGrid folder to the phpGrid folder.
  3. Complete the installation by configuring the conf.php file.

Before we begin coding, we must include the following information in conf.php, the phpGrid configuration file.

1
2
3
4
5
6
define('PHPGRID_DB_HOSTNAME', 'localhost'); //  host name
define('PHPGRID_DB_USERNAME', 'root'); // database user name
define('PHPGRID_DB_PASSWORD', ''); // database password
define('PHPGRID_DB_NAME', 'donation_manager'); // our donation manager database name
define('PHPGRID_DB_TYPE', 'mysql'); // database type
define('PHPGRID_DB_CHARSET','utf8'); // always 'utf8' in MySQL

UI Design

The basic design is simple. It is composed of a single-level top menu bar and a datagrid. In the Reports section, we will add charts using the phpChart.

mockup

The Donations Manager has four menu items. Each item represents a corresponding table in the Donation Manager database.

The include file for the menu is stored in the inc folder named menu.php. The code for the menu is straightforward. For the sake of focus, we will not go into great detail. Feel free to look at the content stored inside the inc folder.

donation manager menu

We have also added a menu item named Reports which we will address in Part II of this tutorial.

Pages

We will use the same page template we used for the CRM and Project Management tutorials.

Donations

Our first Donation Manager page is the Donations page on which we display donation information retrieved from the Donations table in a datagrid.

Remember that each table in the Donation Manager database has the id as the primary key. So, we can easily create our first datagrid with the following two lines of code.

1
2
$dgDonations = new C_DataGrid("SELECT * FROM donations", "id", "donations");
$dgDonations -> display();
phpGrid 101 – A Basic Datagrid

A basic PHP datagrid requires only as little as TWO lines of code.

  1. On the first line, you create the phpGrid object to be displayed.
  2. Then you call display() to render the resulting datagrid on the webpage.

You can learn more about how the basic datagrid works here.

Here’s what our Donations datagrid looks like:

Basic Donations datagrid

Now, we will make a few enhancements to the Donations datagrid.

First of all, we don’t need to show the Donations primary key id as it is only used internally and is meaningless to our users. We can hide it using set_col_hidden().

1
$dgDonations->set_col_hidden('id');

Next, the Amount column is a currency value. We can format this column to be displayed as currency using set_col_currency().

1
$dgDonations->set_col_currency("Amount", "$");

We also want our datagrid to display a human-readable Campaign description and Donor name instead of displaying meaningless integers in columns CampaignId and DonorId. We can easily obtain the campaign description and donor name from Campaigns and Donors table respectively using the set_col_edittype() function.

1
2
$dgDonations->set_col_edittype('CampaignId', 'select', 'select id, CampaignName from campaigns');
$dgDonations->set_col_edittype('DonorId', 'select', "select id, LastName from Donors")

We also want to make the Donations grid editable. We can do this by adding the line:

1
$dgDonations->enable_edit();

The complete code for the Donations datagrid:

1
2
3
4
5
6
7
$dgDonations = new C_DataGrid("SELECT * FROM donations", "id", "donations");
$dgDonations->set_col_hidden('id');
$dgDonations->set_col_edittype('CampaignId', 'select', 'select id, CampaignName from campaigns');
$dgDonations->set_col_edittype('DonorId', 'select', "select id, LastName from Donors");
$dgDonations->set_col_currency("Amount", "$");
$dgDonations->enable_edit();
$dgDonations -> display();

Here’s how the Donations datagrid looks after our enhancements:

Donations datagrid after enhancements

Looks good, doesn’t it? Let’s move on!

Donors

The second page is the Donors page. It contains a list of donors and donation summary information.

A one-to-many relationship exists between the table Donors and Donations because one donor can make one or more donations. The Donations table has a foreign-key field donorid which references the Donors table.

We can join both tables, Donors and Donations by using an INNER JOIN to populate our Donations datagrid.

SQL 101 – INNER JOIN

Use an INNER JOIN to create a one-to-many relationship between two database tables. The table on the “one” side of the “one-to-many” relationship should have a primary key column. The other table has a foreign key that points to the primary key in the first table.

Here’s our SQL statement.

1
2
3
4
5
6
SELECT
 d.id,
 d.FirstName, d.LastName,
 d.Address, d.Email,
FROM donors d
INNER JOIN donations dn ON d.id = dn.donorid

To make our data look more interesting, we create a full name by concatenating the first name FirstName and last name LastName fields with CONCAT, a SQL function that concatenates two or more strings. In MySQL, it has the following syntax:

1
2
3
4
5
6
7
8
CONCAT(expression1, expression2, expression3,...)
[cc]

<p>TO CREATE the donor’s FULL name, we also ADD a blank CHARACTER after FirstName, which adds a SPACE BETWEEN the FIRST AND LAST names. </p>


[cc lang="sql"]
CONCAT(d.FirstName, ' ', d.LastName) AS Name

We also want to display the total amount of donated by a given donor. This is where SQL aggregation functions come in handy. In MySQL, you can use the SUM() function to return the total sum of a numeric column. We name our total TotalDonation.

1
SUM(dn.Amount) AS 'TotalDonation'

Because we want to display the summary information, we need to add a GROUP BY statement that groups identical data in the result-set. In this case, we assume that if the Address and Email fields are them same it means they refer to the same donor. The GROUP BY clause groups records into summary rows for each group. It is typically used with aggregate functions such as COUNT, MAX, MIN, SUM, and AVG.

1
GROUP BY d.Address, d.Email

Putting it all together, here’s the final SQL statement that we will use to create our datagrid.

1
2
3
4
5
6
7
8
SELECT
 d.id,
 concat(d.FirstName, ' ', d.LastName) AS Name,
 d.Address, d.Email,
 SUM(dn.Amount) AS 'TotalDonation'
FROM donors d
INNER JOIN donations dn ON d.id = dn.donorid
GROUP BY d.Address, d.Email

Just in case you were wondering about what the d and dn are for in the SQL statement, they are the SQL table aliases.

SQL 101 – Table Alias

SQL aliases are temporary names used for table or column. Aliases are often used to make column or table names more readable. It only exists for the duration of the query.

Donors Datagrid

Below is the code for our Donors datagrid. It is composed of a phpGrid constructor that uses the above SQL statement and the display() function.

1
2
3
4
5
6
7
8
9
10
11
$dgDonors = new C_DataGrid(
    "SELECT
        d.id,
        concat(d.FirstName, ' ', d.LastName) As Name,
        d.Address, d.Email,
        sum(dn.Amount) As 'TotalDonation'
        FROM donors d
        INNER JOIN donations dn on d.id = dn.donorid
        GROUP BY d.Address, d.Email "
,
    "id", "donors");
$dgDonors -> display();

Our Donations datagrid looks like this:

basic donors datagrid

Let’s add a few things to improve its usability.

First of all, the first column displays the table’s primary key id. We don’t need to show this to our users. Let’s hide it using the set_col_hidden() function.

1
$dgDonors->set_col_hidden('id');

Each donor has an email. We can easily make this field an email hyperlink using set_col_format().

1
$dgDonors->set_col_format('Email', 'email');

The TotalDonation column is a currency field. We can change this column to currency format using set_col_currency().

1
$dgDonors->set_col_currency("TotalDonation", "$");

And both the Name and TotalDonation fields should be read-only.

1
2
$dgDonors->set_col_readonly("Name", true);  
$dgDonors->set_col_readonly("TotalDonation", true);

Finally, we make the Donors datagrid editable I(except for the fields we just made read-only) with the enable_edit() function.

1
$dgDonors->enable_edit();
The complete Donors datagrid code:
1
2
3
4
5
6
7
$dgDonors->set_col_hidden('id');
$dgDonors->set_col_format('Email', 'email');
$dgDonors->set_col_currency("TotalDonation", "$");    
$dgDonors->set_col_readonly("Name", true);  
$dgDonors->set_col_readonly("TotalDonation", true);
$dgDonors->enable_edit();
$dgDonors->display();

Here’s how the Donors datagrid looks like after the changes (with edit window open).

donors datagrid edit

Donation Detail Grid

As one-to-many relationship exists between table Donors and Donations, we can easily present this relationship using the phpGrid master detail feature.

Datagrid 101 – Master Detail

A one-to-many relationship between two data models can be presented in a master-detail format using datagrids.

The detail grid is a regular phpGrid datagrid object and can use the same methods as any other datagrid such as description title, sort, and update etc. The detail grid is dynamically rendered based on the row selected from the parent (master) grid.

We will simply reuse the code from Donations datagrid we created earlier in this tutorial.

1
2
3
4
5
6
$dgDonations = new C_DataGrid("SELECT * FROM donations", "id", "donations");
$dgDonations->set_col_hidden('id');
$dgDonations->enable_edit();
$dgDonations->set_col_edittype('CampaignId', 'select', 'select id, CampaignName from campaigns');
$dgDonations->set_col_edittype('DonorId', 'select', "select id, concat(FirstName, ' ', LastName) from Donors");
$dgDonations->set_col_currency("Amount", "$");

Note that we did NOT include the last line $dgDonations->display().

Finally, we set the master-detail relationship in our code using set_masterdetails(). The second parameter is the foreign-key defined in the detail table Donations. The third parameter is the foreign-key defined in the master table Donors.

1
$dgDonors -> set_masterdetail($dgDonations, 'DonorId', 'id');

A series of phpGrid master-detail demos and how to use them beyond the scope of this tutorial is also available.

Campaigns

The Campaigns page contains campaign information and donations details. Note that a given campaign can receive many donations from one or many donors. Again, we can use phpGrid’s master-detail feature as we what did on the Donors page.

Let’s start with the Campaigns.

Since the table Campaigns and Donations have a one-to-many relationship, we can join the two tables by creating an INNER JOIN.

1
2
3
SELECT c.id, dn.CampaignId, c.CampaignName, c.Description, c.StartDate, c.OrgId,
FROM campaigns c
INNER JOIN donations dn ON c.id = dn.CampaignId

Note that c and dn are the SQL table aliases for the Campaigns and Donations table respectively.

We also want to show the total amount that has been donated to a particular campaign. Again, we can use the SQL aggregation function SUM() to return the total of the Amount column from the Donations table.

1
SUM(dn.Amount) AS 'TotalDonation'

One of the key ways to measure the success of a donation campaign, besides the its total amount of donations received, is the total number of the donations. Here, we introduce another useful SQL aggregation function called COUNT().

1
COUNT(*) AS 'DonationCount'

The COUNT() function, well, as its name suggests, counts the number of rows returned in a SELECT statement. We give it the name DonationCount.

Lastly, since we want to display the campaign summary information, we will add a GROUP BY statement which will group records and print their totals into summary rows for each group.

1
GROUP BY dn.CampaignId, c.CampaignName, c.Description, c.StartDate, c.OrgId
SQL 101 – GROUP BY & Aggregates

Use GROUP BY whenever you need to use the SQL aggregate functions such as COUNT, MAX, SUM, and AVG.

The complete SQL SELECT statement for our Campaigns datagrid looks like this:

1
2
3
4
5
6
SELECT c.id, dn.CampaignId, c.CampaignName, c.Description, c.StartDate,
    COUNT(*) AS 'DonationCount',
    SUM(dn.Amount) AS 'TotalDonation'
    FROM campaigns c
    INNER JOIN donations dn ON c.id = dn.CampaignId
    GROUP BY dn.CampaignId, c.CampaignName, c.Description, c.StartDate

Next, we are going to include a few phpGrid functions to jazz up our Campaigns datagrid.

First of all, as we did with the others, let’s hide the column id.

1
2
$dgCamp->set_col_hidden('id');
$dgCamp->set_col_hidden('CampaignId');

Then, let’s display our TotalDonation field in a currency format.

1
$dgCamp->set_col_currency('TotalDonation', '$');

Don’t forget to make the Campaigns grid editable.

1
$dgCamp->enable_edit();

Lastly, we add a global search by adding the function enable_global_search() which enables a multi-fields global search on any searchable columns. That’s all it takes.

1
$dgCamp->enable_global_search(true);

That’s it for the Campaigns grid. Let’s take a look:

Campaigns datagrid

The complete code for the Campaigns grid:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$dgCamp = new C_DataGrid(
    "SELECT c.id, dn.CampaignId, c.CampaignName,
    c.Description, c.StartDate,
    count(*) As 'DonationCount',
    sum(dn.Amount) As 'TotalDonation'
    FROM campaigns c
    INNER JOIN donations dn on c.id = dn.CampaignId
    GROUP BY dn.CampaignId, c.CampaignName, c.Description, c.StartDate"
,
    "id", "campaigns");
$dgCamp->set_col_hidden('id');
$dgCamp->set_col_hidden('CampaignId');
$dgCamp->enable_edit();
$dgCamp->enable_global_search(true);
$dgCamp->set_col_currency('TotalDonation', '$');

Donations Detail Grid

Remember that we mentioned earlier that the Campaigns and Donations table have a one-to-many relationship? We can present their relationship using the phpGrid master detail feature similar to the way what we did for the Donors and Donations tables.

We will simply reuse the same code we used for the Donations datagrid we made earlier in the tutorial.

1
2
3
4
5
6
$dgDonations = new C_DataGrid("SELECT * FROM donations", "id", "donations");
$dgDonations->set_col_hidden('id');
$dgDonations->enable_edit();
$dgDonations->set_col_edittype('CampaignId', 'select', 'select id, CampaignName from campaigns');
$dgDonations->set_col_edittype('DonorId', 'select', "select id, concat(FirstName, ' ', LastName) from Donors");
$dgDonations->set_col_currency("Amount", "$");

Note that we did NOT include the last line $dgDonations->display().

Finally, we set the master-detail relationship in our code using set_masterdetails(). Campaigns is the master grid, and Donations is the detail grid.

1
$dgCamp -> set_masterdetail($dgDonations, 'CampaignId', 'id');

Thus, the complete code for the Campaigns page is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$dgCamp = new C_DataGrid(
    "SELECT c.id, dn.CampaignId, c.CampaignName, c.Description, c.StartDate,
    COUNT(*) As 'DonationCount',
    SUM(dn.Amount) As 'TotalDonation'
    FROM campaigns c
    INNER JOIN donations dn on c.id = dn.CampaignId
    GROUP BY dn.CampaignId, c.CampaignName, c.Description, c.StartDate"
,
    "id", "campaigns");
$dgCamp->set_col_hidden('id');
$dgCamp->set_col_hidden('CampaignId');
$dgCamp->enable_edit();
$dgCamp->enable_global_search(true);
$dgCamp->set_col_currency('TotalDonation', '$');

// Donations detail grid
$dgDonations = new C_DataGrid("SELECT * FROM donations", "id", "donations");
$dgDonations->set_col_hidden('id')->set_caption('Donations');
$dgDonations->enable_edit();
$dgDonations->set_dimension('1000px');
$dgDonations->set_col_edittype('CampaignId', 'select', 'select id, CampaignName from campaigns');
$dgDonations->set_col_edittype('DonorId', 'select', "select id, concat(FirstName, ' ', LastName) from Donors");
$dgDonations->set_col_currency("Amount", "$");

$dgCamp -> set_masterdetail($dgDonations, 'CampaignId', 'id');
$dgCamp -> display();

This marks the end of the code needed to create the datagrids required for this tutorial. However, we are not done yet. There is still one more page we need to create – Reports. We will cover this section in the Part 2.

Stay tuned!

Run Demo Download Demo Source Code

First published on Medium.

The post A Step-by-Step Guide to Building a Donation Manager from Scratch in PHP – Part I appeared first on phpGrid.

A Step-by-Step Guide to Building a Donation Manager from Scratch in PHP – Part II

$
0
0

In this part of the tutorial, we will continue from where we left off in Build a Donation Manager Part I. You will learn how to use phpChart, an easy-to-use charting and graphing component, that will seamlessly integrates with phpGrid to create professional-looking, interactive reports for your Donation Manager application.

Before we start, we need to install phpChart. To fully benefit from this tutorial, I recommend you obtain the full version of phpChart since the free version – phpChart Lite – supports only the line chart.

Setup phpChart

It is very important that phpGrid and phpChart be kept in its separate folders. Below is the recommended folder hierarchy.

1
2
3
4
5
6
7
www
+-- Donation_Manager
|   |-- phpGrid
|   |   +-- conf.php
|   |-- phpChart
|   |   +-- conf.php
|   +-- ...

That’s it.

Report Design

Our report consists of a bar chart and a pie chart followed by a campaign summary datagrid. The datagrid provides the data used to plot the two charts.

reports mockup

phpGrid phpChart Integration

First of all, include both conf.php files (phpGrid and phpChart) at the beginning of the code.

1
2
require_once("phpGrid/conf.php");
require_once("phpChart/conf.php");

Bar Chart

The first chart we will create is the bar chart. Below is the complete code to create an EMPTY bar chart. We first must create an empty chart is because the campaign data used to plot the chart is not available at the time when the chart is initialized.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$pc = new C_PhpChartX(array(array(null)),'BarChart');
$pc->add_plugins(array('canvasTextRenderer','canvasAxisTickRenderer', 'pointLabels'),true);
$pc->set_animate(true);
$pc->set_series_default(array(
        'renderer'=>'plugin::BarRenderer',
        'rendererOptions' => array('barWidth'=>60),
        'pointLabels'=> array('show'=>true)
        ));
$pc->set_axes(array(
     'xaxis'=>array(
        'label'=>'Campaign',
        'renderer'=>'plugin::CategoryAxisRenderer',
        'rendererOptions'=>array('tickRenderer'=>'plugin::CanvasAxisTickRenderer'),
        'ticks'=>array(null),
        'tickOptions'=>array(
                'angle'=>-35,
                'fontStretch'=>1)),
    'yaxis'=>array('label'=>'Total Donations')
));
$pc->draw(600,400);

Let’s break this baby apart. For the sake of simplicity, we will only cover high level implementation and skip over details where the code is actually self-explanatory.

The first line is the constructor. We pass an empty array, array(null), as the series data because we don’t wish to have any data displayed in the bar chart when it is first rendered. We also give our graph an unique name, BarGraph.

1
$pc = new C_PhpChartX(array(array(null)),'BarGraph');

Next, we use the add_plugins() function to include some additional new elements to our bar chart. For this tutorial, we will include the canvasTextRenderer, canvasAxisTickRenderer, and pointLabels plugins. A list of supported plugins can be found here.

1
$pc->add_plugins(array('canvasTextRenderer','canvasAxisTickRenderer', 'pointLabels'),true);

In the series default function, be sure to set the renderer type to BarRenderer. We can also set the rendererOptions and pointLabels properties here.

1
2
3
4
5
$pc->set_series_default(array(
            'renderer'=>'plugin::BarRenderer',
            'rendererOptions' => array('barWidth'=>60),
            'pointLabels'=> array('show'=>true)
            ));

A bar chart has two sets of data – one set for the x axis and another for the y. In this example, the x axis shows the total amount donated to a given campaign and the y axis displays the name of the campaign. We can set the properties for both x and y in one statement by using the set_axes() function. Notice how label, renderer, and ticks properties are used.

Complete documentation for phpChart methods and properties documentation can be found online.

1
2
3
4
5
6
7
8
9
10
11
$pc->set_axes(array(
     'xaxis'=>array(
        'label'=>'Campaign',
        'renderer'=>'plugin::CategoryAxisRenderer',
        'rendererOptions'=>array('tickRenderer'=>'plugin::CanvasAxisTickRenderer'),
        'ticks'=>array(null),
        'tickOptions'=>array(
                'angle'=>-35,
                'fontStretch'=>1)),
    'yaxis'=>array('label'=>'Total Donations')
));

Finally, the last line reserves space for a chart that is 600px high and 400px wide.

1
$pc->draw(600,400);

Pie Chart

Now let’s move on to the second chart in our report. Below is the entire code to create an EMPTY pie chart.

1
2
3
4
5
6
7
8
9
$pc2 = new C_PhpChartX(array(array(null)),'PieChart');
$pc2->set_series_default(array( 'shadow'=> false,
    'renderer'=> 'plugin::PieRenderer',
    'rendererOptions'=> array(
      'sliceMargin'=> 3,
      'showDataLabels'=> true )
  ));
$pc2->set_legend(array('show'=>true,'location'=> 'w'));
$pc2->draw(600,400);

Let’s do a quick review of the above script.

The first line is the phpChart constructor. Again, the first parameter is an empty array, array(null), as the series data will be loaded later from the Campaign Summary datagrid.

1
$pc2 = new C_PhpChartX(array(array(null)),'PieChart');

We then set the renderer to PieRenderer and set the its properties using the series default function.

1
2
3
4
5
6
$pc2->set_series_default(array( 'shadow'=> false,
    'renderer'=> 'plugin::PieRenderer',
    'rendererOptions'=> array(
      'sliceMargin'=> 3,
      'showDataLabels'=> true )
  ));

We also want to display the legend to the west, or left, of the chart.

1
$pc2->set_legend(array('show'=>true,'location'=> 'w'));

Lastly, we draws the pie chart.

1
$pc2->draw(600,400);

You should now have two blank charts on the page.

blank charts

Campaign Summary Datagrid

The Campaign datagrid used in this report is the same as what was used to create the Campaign page in Part 1. We just need to add one more thing – an event handler.

In phpGrid, we can add an event handler with the add_event() function. add_event() binds an event handler, which is essentially a JavaScript function, for a specific phpGrid event. A list of possible events can be found here.

Since we must wait for the datagrid to finish loading before sending its data needed to plot the charts, we use the event jqGridLoadComplete.

phpGrid 101 – jqGridLoadComplete Event

jqGridLoadComplete is the last event that occurs once the whole datagrid body has finished loading. Note that the grid body will be reloaded if the user changes the sorting of a column or sets a filter.

Send Data Using Javascript

The following is the Javascript event handler for jqGridLoadComplete.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function(status, rowid)
{
    var barData1 = [];
    var barData2 = [];

    d1 = $('#campaigns').jqGrid('getCol', 'TotalDonation', false);
    d2 = $('#campaigns').jqGrid('getCol', 'CampaignName', false);

    npoints = d1.length;
    for(var i=0; i &lt; npoints; i++){
        barData1[i] = [i+1, parseInt(d1[i])];
        barData2[i] = [i+1, d2[i]];
    }
    _BarChart.series[0].data = barData1;
    _BarChart.axes.xaxis.ticks = barData2;
    _BarChart.replot({resetAxes:true});

    var pieData = [];
    for(var j=0; j &lt; barData1.length; j++)
    {
        pieData.push([barData2[j][1],barData1[j][1]]);
    }
    // console.log(pieData);
    _PieChart.series[0].data = pieData;
    _PieChart.replot({resetAxes:true});
   }

The Javascript function is the bread and butter that makes our report come alive. It requires a certain level of knowledge of basic Javascript.

Right off the bat, we declare two empty arrays to store x and y axis data points. Since we are now using JavaScript, the syntax will be different from that used in PHP.

1
2
var barData1 = [];
var barData2 = [];

The following two lines return data from the datagrid column TotalDonation and CampaignName:

1
2
d1 = $('#campaigns').jqGrid('getCol', 'TotalDonation', false);
d2 = $('#campaigns').jqGrid('getCol', 'CampaignName', false);

The for loop iterates each column and then stores the results in the x and y axis arrays.

1
2
3
4
5
npoints = d1.length;
for(var i=0; i &lt; npoints; i++){
    barData1[i] = [i+1, parseInt(d1[i])];
    barData2[i] = [i+1, d2[i]];
}

Next, we assign the barData from the datagrid to the bar chart object. Lastly always call jqPlot replot function to load the chart.

1
2
3
_BarChart.series[0].data = barData1;
_BarChart.axes.xaxis.ticks = barData2;
_BarChart.replot({resetAxes:true});
phpChart 101 – JavaScript Chart Object Name

The JavaScript chart object name is the same as the name used in the phpChart constructor, e.g. BarChart, prefixed with the underscore character “_”.

We have just completed our bar chart.

Next, we move on to the pie chart. The JavaScript code for this is similar to what we used for the bar chart except that a pie chart does not have x and y axes. Instead, it uses a two-dimensional array.

1
pieData.push([barData2[j][1],barData1[j][1]]);

bar chart & pie chart in donation manager

That’s all there is to it!

Conclusion

Hopefully, after finishing this tutorial, you have become a true campaign master yourself – one who is capable of developing a fully functional donation manager system from start to finish.

Run Demo Download Demo Source Code

The post A Step-by-Step Guide to Building a Donation Manager from Scratch in PHP – Part II appeared first on phpGrid.

Creating a Custom Inventory Management Application in PHP and MySQL

$
0
0

Introduction

You do not need bloated enterprise software to effectively track your inventory. This tutorial will help you develop your own custom inventory tracking system so you can make smart inventory decisions based on timely and accurate inventory data.

System Requirements

Our Inventory System requires the standard commercial phpGrid and phpChart license as it needs a few advanced features from both components.

  • PHP 5.3+
  • MySQL or MariaDB
  • phpGrid
  • phpChart (for reports)

What is in an Inventory Management System

An inventory management system has several critical components. At its core, inventory control works by tracking the two main functions of a warehouse — receiving (incoming) and shipping (outgoing). Other activities such as movement, or relocating, of inventory also take place. Raw materials are decremented and finished goods are incremented.

  • Incoming shipments
  • Outgoing orders
  • Inventory
  • Suppliers

Inventory System Database Diagram

Typically, an inventory system has four basic elements – products, purchases, orders, and suppliers – which must be tracked based on their location, SKU, and quantity. Current inventory, or products on hand, is updated by tracking incoming shipments and outgoing orders. Order alerts can be set to trigger when inventory levels fall below custom-defined minimum levels.

Inventory Manager DB Schema

Setting up the Inventory Manager Database

Download the InventoryManager.sql SQL script from this tutorial’s GitHub repo, and then execute the script using a MySQL tool such as MySQL Workbench. This will create a new database named InventoryManager as well as the tables needed for this tutorial.

Set up phpGrid

We will use a datagrid component by phpGrid to handle all internal database CRUD (Create, Remove, Update, and Delete) operations.

Be sure to download a copy of phpGrid before you proceed.

To install phpGrid, follow these steps:

  1. Unzip the phpGrid download file.
  2. Upload the phpGrid folder to the phpGrid folder.
  3. Complete the installation by configuring the conf.php file.

Before we begin coding, we must include the following information in conf.php, the phpGrid configuration file.

1
2
3
4
5
6
define('PHPGRID_DB_HOSTNAME', 'localhost'); //  host name
define('PHPGRID_DB_USERNAME', 'root'); // database user name
define('PHPGRID_DB_PASSWORD', ''); // database password
define('PHPGRID_DB_NAME', 'InventoryManager'); // our donation manager database name
define('PHPGRID_DB_TYPE', 'mysql'); // database type
define('PHPGRID_DB_CHARSET','utf8'); // always 'utf8' in MySQL

Creating the User Interface (UI)

The application has four pages:

  • Current Inventory
  • Incoming Purchases
  • Orders to Ship
  • Reports

Inventory UI

The include file for the menu is stored in an inc folder named menu.php. The code for the menu is straightforward. For the sake of focus, we will not go into great detail. Feel free to look at the code inside the inc folder.

We have also added a menu item named Reports.

Menu

Pages

We will use the same page template we used for the CRM and Project Management tutorials.

Current Inventory

Let’s start with the Current Inventory page.

Incoming purchases increase the inventory while outgoing orders decrease it. From a master-detail perspective, the Current Inventory has not one, but two detail datagrids – the Purchases (incoming purchases) and the Orders (outgoing orders).

Therefore, the Current Inventory page is composed of one master grid – the Current Inventory in stock – and two detail grids – Incoming Purchases and Outgoing Orders. We can easily present these relationships using the phpGrid one master and multiple detail datagrids feature.

If you have read the last tutorial Building a Donation Manager from Scratch, you will have no problem following the code below.

Note the use of the set_col_format() function used to format the integers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$dgProd = new C_DataGrid('SELECT * FROM products', 'id', 'products');
$dgProd->set_col_hidden('id', false);
$dgProd->enable_autowidth(true)->set_dimension('auto', '200px')->set_pagesize(100);

$dgProd->set_col_title('ProductName', 'Name');
$dgProd->set_col_title('PartNumber', 'Part Number');
$dgProd->set_col_title('ProductLabel', 'Label');
$dgProd->set_col_title('StartingInventory', 'Starting Inventory');
$dgProd->set_col_title('InventoryReceived', 'Inventory Received');
$dgProd->set_col_title('InventoryShipped', 'Inventory Shipped');
$dgProd->set_col_title('InventoryOnHand', 'Inventory On Hand');
$dgProd->set_col_title('MinimumRequired', 'Minimum Required');

$dgProd->set_col_format('StartingInventory', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryReceived', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryShipped', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryOnHand', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('MinimumRequired', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->enable_edit('FORM');

That’s it for the Current Inventory datagrid. Here’s what it looks like so far:

products

Now, let’s make a few changes to enhance our Product datagrid.

First of all, we will add some conditional formatting so that whenever the InventoryOnHand is set to zero or a negative value, it is displayed using a different background color. We will use the set_conditional_format() function for this purpose.

1
2
3
4
5
 $dgProd->set_conditional_format(
    'InventoryOnHand', 'CELL',
        array("condition"=>"lt",
          "value"=>"1",
          "css"=> array("color"=>"red","background-color"=>"#DCDCDC")));

The above code adds a display condition so that whenever the InventoryOnHand field has a value that is less than (lt) one, the text color changes to red and the background color to dark gray (#DCDCDC).

Secondly, whenever the InventoryOnHand is less than the value shown in MinimumRequired, we would like to alert the user by displaying it in a prominent background color such as gold. To compare values between two fields, we must switch to Javascript because the set_conditional_format() function only works with a single field.

The code below uses a for loop to iterate through each row in the Products datagrid. It compares the inventoryOnHand with theminimumRequired and, when condition is met, it will use thesetCell function to change the background color.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 $onGridLoadComplete = &lt;&lt;&lt;ONGRIDLOADCOMPLETE
function(status, rowid)
{
    var ids = jQuery("#products").jqGrid('getDataIDs');
    for (var i = 0; i &lt; ids.length; i++)
    {
        var rowId = ids[i];
        var rowData = jQuery('#products').jqGrid ('getRowData', rowId);

        var inventoryOnHand = $("#products").jqGrid("getCell", rowId, "InventoryOnHand");
        var minimumRequired = $("#products").jqGrid("getCell", rowId, "MinimumRequired");

        // compare two dates and set custom display in another field "status"
        console.log(inventoryOnHand + " | " + minimumRequired);
        if(parseInt(inventoryOnHand) &lt; parseInt(minimumRequired)){

            $("#products").jqGrid("setCell", rowId, "PartNumber", '', {'background-color':'gold'});

        }
    }

}
ONGRIDLOADCOMPLETE;
$dgProd->add_event("jqGridLoadComplete", $onGridLoadComplete);

You can learn more about comparing multiple cell values on the phpGrid support website,

Next, on the same page, we need to see the purchases coming in (Incoming) and orders going out (Outgoing) for a specific product.

Purchases Detail Grid (Incoming)

1
2
3
4
5
6
 // Purchases detail grid
$dgPur = new C_DataGrid('SELECT id, PurchaseDate, ProductId, NumberReceived, SupplierId FROM purchases', 'id', 'purchases');
$dgPur->set_col_hidden('id', false)->set_caption('Incoming Purchases');
$dgPur->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgPur->set_col_edittype('SupplierId', 'select', "select id, supplier from suppliers");
$dgPur->set_dimension('800px');

Orders Detail Grid (Outgoing)

1
2
3
4
5
6
 // Orders detail grid
$dgOrd = new C_DataGrid('SELECT id, OrderDate, ProductId, NumberShipped, First, Last FROM orders', 'id', 'orders');
$dgOrd->set_sortname('OrderDate', 'DESC')->set_caption('Outgoing Orders');
$dgOrd->set_col_hidden('id', false);
$dgOrd->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgOrd->set_dimension('800px');

Both detail grids use the same foreign key ProductId to link to the master datagrid – Products.

1
2
 $dgProd->set_masterdetail($dgPur, 'ProductId', 'id');
$dgProd->set_masterdetail($dgOrd, 'ProductId', 'id');

Finally, our complete code to manage the Current Inventory page is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
 $dgProd = new C_DataGrid('SELECT * FROM products', 'id', 'products');
$dgProd->set_col_hidden('id', false);
$dgProd->enable_autowidth(true)->set_dimension('auto', '200px')->set_pagesize(100);

$dgProd->set_col_title('ProductName', 'Name');
$dgProd->set_col_title('PartNumber', 'Part Number');
$dgProd->set_col_title('ProductLabel', 'Label');
$dgProd->set_col_title('StartingInventory', 'Starting Inventory');
$dgProd->set_col_title('InventoryReceived', 'Inventory Received');
$dgProd->set_col_title('InventoryShipped', 'Inventory Shipped');
$dgProd->set_col_title('InventoryOnHand', 'Inventory On Hand');
$dgProd->set_col_title('MinimumRequired', 'Minimum Required');

$dgProd->set_col_format('StartingInventory', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryReceived', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryShipped', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('InventoryOnHand', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));
$dgProd->set_col_format('MinimumRequired', 'integer', array('thousandsSeparator'=>',', 'defaultValue'=>'0'));

$dgProd->set_conditional_format('InventoryOnHand', 'CELL', array("condition"=>"lt",
                                                  "value"=>"1",
                                                  "css"=> array("color"=>"red","background-color"=>"#DCDCDC")));

$onGridLoadComplete = &lt;&lt;&lt;ONGRIDLOADCOMPLETE
function(status, rowid)
{
    var ids = jQuery("#products").jqGrid('getDataIDs');
    for (var i = 0; i &lt; ids.length; i++)
    {
        var rowId = ids[i];
        var rowData = jQuery('#products').jqGrid ('getRowData', rowId);

        var inventoryOnHand = $("#products").jqGrid("getCell", rowId, "InventoryOnHand");
        var minimumRequired = $("#products").jqGrid("getCell", rowId, "MinimumRequired");

        // compare two dates and set custom display in another field "status"
        console.log(inventoryOnHand + " | " + minimumRequired);
        if(parseInt(inventoryOnHand) &lt; parseInt(minimumRequired)){

            $("#products").jqGrid("setCell", rowId, "PartNumber", '', {'background-color':'gold'});

        }
    }

}
ONGRIDLOADCOMPLETE;
$dgProd->add_event("jqGridLoadComplete", $onGridLoadComplete);
$dgProd->enable_edit('FORM');

// Purchases detail grid
$dgPur = new C_DataGrid('SELECT id, PurchaseDate, ProductId, NumberReceived, SupplierId FROM purchases', 'id', 'purchases');
$dgPur->set_col_hidden('id', false)->set_caption('Incoming Purchases');
$dgPur->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgPur->set_col_edittype('SupplierId', 'select', "select id, supplier from suppliers");
$dgPur->set_dimension('800px');

// Orders detail grid
$dgOrd = new C_DataGrid('SELECT id, OrderDate, ProductId, NumberShipped, First, Last FROM orders', 'id', 'orders');
$dgOrd->set_sortname('OrderDate', 'DESC')->set_caption('Outgoing Orders');
$dgOrd->set_col_hidden('id', false);
$dgOrd->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgOrd->set_dimension('800px');

$dgProd->set_masterdetail($dgPur, 'ProductId', 'id');
$dgProd->set_masterdetail($dgOrd, 'ProductId', 'id');
$dgProd->display();

Here’s the a snapshot of the inventory page:

Current inventory

Incoming Purchases

The next page is the Incoming Purchase page. It is similar to the Purchase Detail Grid we saw when setting up the Current Inventory page. We group the purchases by ProductId and display the sum inNumberReceived. Any incoming purchases will increase the inventory.

1
2
 $dgPur -> set_group_properties('ProductId', false, true, true, false);
$dgPur -> set_group_summary('NumberReceived','sum');

The complete code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 $dgPur = new C_DataGrid('SELECT id, PurchaseDate, ProductId, NumberReceived, SupplierId FROM purchases', 'id', 'purchases');
$dgPur->set_col_hidden('id', false);

$dgPur->set_col_title('PurchaseDate', 'Date of Purchase');
$dgPur->set_col_title('ProductId', 'Product');
$dgPur->set_col_title('NumberReceived', 'Number Received');
$dgPur->set_col_title('SupplierId', 'Supplier');

$dgPur->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");
$dgPur->set_col_edittype('SupplierId', 'select', "select id, supplier from suppliers");

// $dgPur->enable_edit('FORM');
$dgPur->set_pagesize(100);

$dgPur->set_col_width('PurchaseDate', '50px');
$dgPur->set_col_width('NumberReceived', '35px');

$dgPur -> set_group_properties('ProductId', false, true, true, false);
$dgPur -> set_group_summary('NumberReceived','sum');

$dgPur->enable_autowidth(true);
$dgPur->display();

Here’s a screenshot of our Incoming Purchases page with grouping enabled:

Incoming purchases

Outgoing Orders

The next page is the Outgoing Orders page. It is similar to the Orders Detail Grid from the Current Inventory page. Here, we will introduce an advanced function called set_grid_method().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 $dgOrd = new C_DataGrid('SELECT id, OrderDate, ProductId, NumberShipped, First, Last FROM orders', 'id', 'orders');
$dgOrd->set_sortname('OrderDate', 'DESC');
$dgOrd->set_col_hidden('id', false);

$dgOrd->set_col_title('OrderDate', 'Order Date');
$dgOrd->set_col_title('ProductId', 'Product');
$dgOrd->set_col_title('NumberShipped', 'Number Shipped');

$dgOrd->set_col_edittype('ProductId', 'select', "select id, ProductLabel from products");

// $dgOrd->enable_edit('FORM');
$dgOrd->set_pagesize(100);

$dgOrd->set_col_width('OrderDate', '30px');
$dgOrd->set_col_width('NumberShipped', '35px');
$dgOrd->set_col_width('First', '20px');
$dgOrd->set_col_width('Last', '20px');

$dgOrd->set_grid_method('setGroupHeaders', array(
                                array('useColSpanStyle'=>true),
                                'groupHeaders'=>array(
                                        array('startColumnName'=>'First',
                                              'numberOfColumns'=>2,
                                              'titleText'=>'Customer Name') )));

$dgOrd->enable_autowidth(true);
$dgOrd->display();

Summary

This tutorial builds a simple and extendable inventory system in less than 50 lines of code. The progressive style of these tutorials also helps the reader to ultimately become more familar and comfortable with phpGrid by introducing a limited number of new phpGrid features in each one.

What’s Coming Up

This marks the end of the code needed to create the datagrids required for this tutorial. However, we are not done yet. There is still one more page we need to create — Reports. We will cover that after the jump.


Reports

What is an inventory system good for without some of type of report? In this section, you will learn how to use phpChart – which seamlessly integrates with phpGrid – to create visually pleasing and useful reports for your Inventory Manager application.

Here’s what our page will look like when it’s done:

inventory reports

Before we start, we need to install phpChart. It is recommended that you obtain the full version of phpChart since the free version – phpChart Lite – supports only the line chart.

Setup phpChart

It’s important that we keep phpGrid and phpChart in separate folders. Below is the recommended folder hierarchy.

1
2
3
4
5
6
7
www
+-- Donation_Manager
|   |-- phpGrid
|   |   +-- conf.php
|   |-- phpChart
|   |   +-- conf.php
|   +-- ...

Report Design

We will place a pie chart next to an inventory summary grid. The datagrid provides the series data to plot the pie chart.

Reports UI

phpGrid and phpChart Integration

First of all, include calls to both conf.php files at the beginning of the code.

1
2
require_once("phpGrid/conf.php");
require_once("phpChart/conf.php");

Pie Chart

Below is the complete code to create our pie chart:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 $pc = new C_PhpChartX(array(array(null)), 'PieChart');
$pc->set_title(array('text'=>'Current Inventory Summary'));
$pc->set_series_default(array( 'shadow'=> false,
    'renderer'=> 'plugin::PieRenderer',
    'rendererOptions'=> array(
      'showDataLabels' => true,
      'highlightMouseOver' => true,
      'startAngle'=> 180,
      'sliceMargin'=> 4,
      'showDataLabels'=> true )
  ));
$pc->set_legend(array('show'=>true,'location'=> 'w'));
// remove background
$pc->set_grid(array(
    'background'=>'white',
    'borderWidth'=>0,
    'borderColor'=>'#000000',
    'shadow'=>false));
$pc->add_custom_js("
        $('#PieChart').bind('jqplotDataHighlight',
            function (ev, seriesIndex, pointIndex, data) {
               $('#label_info').text(data);      
            }
        );
    "
);
$pc->draw(660,400);

Let’s walk through the code.

The first line is the constructor. We pass array(null) as the series data because we don’t wish to have any data displayed in the pie chart initially as the inventory data used to plot the chart is not yet available when it is first initialized. The data is fed from the datagrid later in JSON.

We also give our chart a unique name, PieChart.

1
 $pc = new C_PhpChartX(array(array(null)), 'PieChart');

Next, we give it a title. Nothing fancy here.

1
 $pc->set_title(array('text'=>'Current Inventory Summary'));

Once we have the title, we call the series default function to set the renderer to PieRenderer. Unlike a bar chart, a pie chart does not have a Y axis.

We can also set the rendererOptions property. We will not go into each option in detail here, but you can find more information in the online documentation.

1
2
3
4
5
6
7
8
 $pc->set_series_default(array( 'shadow'=> false,
    'renderer'=> 'plugin::PieRenderer',
    'rendererOptions'=> array(
      'highlightMouseOver' => true,
      'startAngle'=> 180,
      'sliceMargin'=> 4,
      'showDataLabels'=> true )
  ));

We also want to show a legend. The set_legend command below shows the legend to the west (noted byw) or to the left of the pie chart.

1
 $pc->set_legend(array('show'=>true,'location'=> 'w'));

We will also remove the border and the background.

1
2
3
4
5
 $pc->set_grid(array(
    'background'=>'white',
    'borderWidth'=>0,
    'borderColor'=>'#000000',
    'shadow'=>false));

Finally, we draw our chart by giving it a height and width in pixels.

1
 $pc->draw(660,400);

However, if you execute the code now, you will not see the chart because the data used to render it isn’t available yet.

Inventory Summary Datagrid

Here, we will use the same the inventory datagrid as we did in the Products page. We just need to add one more thing – an event handler.

In phpGrid, we can add an event handler with the [add_event()] (https://phpgrid.com/documentation/add_event/) function. add_event() binds an event handler, which is essentially a JavaScript function, to a specific phpGrid event. A list of possible events can be found here.

Since we must wait for the datagrid to finish loading before it can send the data to plot the chart, we use the event jqGridLoadComplete.

phpGrid 101 – jqGridLoadComplete Event

jqGridLoadComplete is last event that occurs once the whole datagrid body has finished loading. Note that the grid body will be reloaded if the user changes the sort order of a column or sets a filter.

Send Data Using Javascript

The following is the Javascript event handler for jqGridLoadComplete.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <span class="hljs-function">function(status, rowid)
{</span>
    var dataX = [];
    var dataY = [];

    d1 = $('#products').jqGrid('getCol', 'ProductLabel', false);
    d2 = $('#products').jqGrid('getCol', 'InventoryReceived', false);

    npoints = d1.length;
    for(var i=0; i &lt; npoints; i++){
        dataX[i] = [i+1, d1[i]];
        dataY[i] = [i+1, parseInt(d2[i])];
    }

    var pieData = [];
    for(var j=0; j &lt; dataX.length; j++)
    {
        pieData.push([dataX[j][1], dataY[j][1]]);
    }
    console.log(pieData);
    _PieChart.series[0].data = pieData;
    _PieChart.replot({resetAxes:true});
}

The complete code:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 $dgProd = new C_DataGrid('SELECT id, ProductLabel, InventoryReceived FROM products', 'id', 'products');
$dgProd->set_col_hidden('id', false);
$dgProd->set_dimension('auto', 'auto')->set_pagesize(100);
$onGridLoadComplete = &lt;&lt;&lt;ONGRIDLOADCOMPLETE
function(status, rowid)
{
    var dataX = [];
    var dataY = [];

    d1 = $('#products').jqGrid('getCol', 'ProductLabel', false);
    d2 = $('#products').jqGrid('getCol', 'InventoryReceived', false);
    d3 = $('#products').jqGrid('getCol', 'InventoryShipped', false);
    d4 = $('#products').jqGrid('getCol', 'InventoryOnHand', false);


    npoints = d1.length;
    for(var i=0; i &lt; npoints; i++){
        dataX[i] = [i+1, d1[i]];
        dataY[i] = [i+1, parseInt(d2[i])];
    }

    var pieData = [];
    for(var j=0; j &lt; dataX.length; j++)
    {
        pieData.push([dataX[j][1], dataY[j][1]]);
    }
    console.log(pieData);
    _PieChart.series[0].data = pieData;
    _PieChart.replot({resetAxes:true});
}
ONGRIDLOADCOMPLETE;
$dgProd->add_event("jqGridLoadComplete", $onGridLoadComplete);
$dgProd->display();

Now there you have it. Your just built your very first inventory management system from scratch using only PHP and MySQL!

Live Demo!

Github Download

Github Download

The post Creating a Custom Inventory Management Application in PHP and MySQL appeared first on phpGrid.

Tagging with autocomplete

$
0
0

To enable tagging, you can set the type of grid edit control to autocomplete with set_col_edittype(), and set the LAST parameter to true.

In the demo below, edit Office Code in the pop-up form to see the tagging feature.

1
2
3
4
5
$dg = new C_DataGrid("select employeeNumber, lastName, firstName, isActive, officeCode, extension from employees", "employeeNumber", "employees");
$dg -> enable_edit("FORM", "CRUD");
$dg -> set_col_edittype("officeCode", "autocomplete", "Select officeCode,city from offices",true);
$dg -> enable_search(true);
$dg -> display();

Live Demo

The post Tagging with autocomplete appeared first on phpGrid.


Excel Editing

$
0
0

Set the edit type to CELL enables datagrid to behave like an Excel spreadsheet. It is advisable to also enable keyboard navigation with enable_kb_nav().

  • Use keyboard arrow keys to navigate the table cell like Excel.
  • Press Enter key to edit a cell. Enter again to save.
  • While editing, press Tab key to move the next adjacent cell. Any changes are automatically saved.

 

1
2
3
4
5
6
7
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->enable_autowidth(true)->enable_autoheight(true);
$dg->set_pagesize(100); // need to be a large number
$dg->set_scroll(true);
$dg->enable_kb_nav(true);
$dg->enable_edit('CELL');
$dg -> display();

 


Live Demo
!

The post Excel Editing appeared first on phpGrid.

enable_pagecount()

$
0
0
  • Parameters:
    • $page_count: boolean: true or false.
  • Description:
    • Enable page count in the pager. Default to true. Set to false to optimize performance for very large (e.g. millions) database table.
  • Example:

 

1
$dg -> enable_pagecount(false);

The post enable_pagecount() appeared first on phpGrid.

Loading from Large Database Table with 3 Million Records!

$
0
0

The total record count is usually one of the most expensive database operations due to sequential scan reading information of every row. When the table is very large, the performance takes a huge hit.

With a large database, we can simply disable the counting operation by calling enable_pagecount() and pass parameter “false”.

1
$dg->enable_pagecount(false);

Below is the entire code for the demo. Note that the table salaries has nearly 3 million records!

1
2
3
4
5
$dg = new C_DataGrid("SELECT * FROM salaries", "emp_no", "salaries")
$dg->enable_edit('INLINE')->set_dimension('800px');
$dg->enable_pagecount(false);
$dg->enable_export(true);
$dg -> display();

In general, to improve overall performance of very large database tables, it is advisable to:

  • Use either an INT or BIGINT datatype than say a GUID
  • Partitioning may reduce the size of indexes, effectively reducing the table size
  • More memory or even SSD drive can work wonders!
  • Remove any unnecessary indexes on the table
  • Remove SELECT COUNT(*) and always include a query filter.

The post Loading from Large Database Table with 3 Million Records! appeared first on phpGrid.

Tagging with autocomplete

$
0
0

To enable tagging, you can set the type of grid edit control to autocomplete with set_col_edittype(), and set the LAST parameter to true.

In the demo below, edit Office Code in the pop-up form to see the tagging feature.

1
2
3
4
5
$dg = new C_DataGrid("select employeeNumber, lastName, firstName, isActive, officeCode, extension from employees", "employeeNumber", "employees");
$dg -> enable_edit("FORM", "CRUD");
$dg -> set_col_edittype("officeCode", "autocomplete", "Select officeCode,city from offices",true);
$dg -> enable_search(true);
$dg -> display();

Live Demo

The post Tagging with autocomplete appeared first on phpGrid.

Excel Editing

$
0
0

Set the edit type to CELL enables datagrid to behave like an Excel spreadsheet. It is advisable to also enable keyboard navigation with enable_kb_nav().

  • Use keyboard arrow keys to navigate the table cell like Excel.
  • Press Enter key to edit a cell. Enter again to save.
  • While editing, press Tab key to move the next adjacent cell. Any changes are automatically saved.

 

1
2
3
4
5
6
7
$dg = new C_DataGrid("SELECT * FROM orders", "orderNumber", "orders");
$dg->enable_autowidth(true)->enable_autoheight(true);
$dg->set_pagesize(100); // need to be a large number
$dg->set_scroll(true);
$dg->enable_kb_nav(true);
$dg->enable_edit('CELL');
$dg -> display();


Live Demo
!

The post Excel Editing appeared first on phpGrid - PHP Datagrid.

Viewing all 107 articles
Browse latest View live