phpReport Manual¶
Edition for phpReport 2.0
by Günter Pöhl
This work is licensed under the GNU Lesser General Public Licensce (LGPL) v3.0
Introduction¶
phpReport is designed to be the backbone for all applications needing control over group changes or when calculation of totals and subtotals is required. This is usually the case for reports but there are a lot of other use cases.
phpReport integrates into any framework without configuration. You’ll never have do extend your classes to use phpReport. So your application can still extend from any framework class.
Use of phpReport is very simple even when you work with very complex data structures.
Data retrieval is done by your own (framework) methods. phpReport will work with this data no matter if you provide a data set or an multi dimensional array. Joining data, even between different sources, is also easy to accomplish.
Getting started¶
After instantiation of the report class call the data() method to specifiy which the data handler to be used. The data handler is responsible to return values from a data row. Out of the box there are an ArrayDataHandler and an ObjectDataHandler. You can also use the ‘array’ or ‘object’ aliases.
Then call the group() method for each group that will be controlled.
Use the aggregate() method to get aggregate functions for an field / attribute. The sheet() method organizes these in an horizontal way like in a spreadsheet.
Then pass your data to the run() method.
At certain events defined actions will be executed. As you can imagine thats the place to do whatever needs to be done.
Note
You have full access to all your existing models. No matter if these are data models or models implementing your business rules.
A report which controls two groups and summarizes totals may look like this example.
use gpoehl\phpreport\Report;
require_once(__DIR__ . '/../vendor/autoload.php');
class MyFirstReport {
// The report object. Use $rep->output to render the output.
public $rep;
/**
* It might also be a good idea to instantiate the Report in your
* controller.
*/
public function __construct($data){
// initialize report
$this->rep = (new Report($this))
->group('customer')
->group('invoice', 'invoiceID')
->compute('sales', fn($row) => $row->amount * $row->price);
// Start execution. $data is an iterable having some data rows
$this->rep->run($data);
}
public function init(){
return "<h1>My very first report</h1>";
}
public function customerHeader($customer, $row){
return "<h2>Customer $customer</h2>" . $customer->address;
}
public function invoiceHeader($invoice, $row){
return "<h3>Invoice ID = $invoice</h3>";
}
// Will be called for each data row
public function detail($row, $rowKey){
return "<br>$row->item: $row->description";
}
// $row in footer methods is the previous row, not the one which triggered the group change.
public function invoiceFooter($invoice, $row){
return "Total sales for invoice $invoice = " . $this->rep->total->sales->sum();
}
public function customerFooter($customer, $row){
return "Total sales for customer $customer = " . $this->rep->total->sales->sum();
}
public function totalFooter(){
return
"Total sales = $this->rep->total->sales->sum()" .
"Total number of customers: $this->rep->gc->customer->sum()" .
"Total number of invoices: $this->rep->gc->invoice->sum()" .
"Total number of rows: $this->rep->rc->sum()" ;
}
}
Main features are:
- Data handling
In the most simple form you will call the run method and pass your dataset to this method. phpReport will the iterate over this dataset and execute certain actions.
It is not required to build a dataset upfront. You can optionally call the run method without any data and call the next method once for each data row. This might save a lot of memory and processing time.
phpReport is also able to handle multi-dimensional arrays. Calling the data method tells which element contains the sub-array. phpReport will then iterate of the sub-array. Sub-array can also have elements where you want specific actions when the value changes. So call the group method after the data method to declare this element. Same is true for values to be aggregated.
phpReport might also getting related data to a given row. See data section for details. Out of the box phpReport offers row counters.
- Aggregating values
With phpReport it’s easy to aggregate values. While calling the aggregate method your values are cumulated. Your might also let phpReport count how often you got a not null or not zero value as well as figure out the min and max value.
- Sheets
Sheets are a very powerful to aggregate values horizontally. Assume you want to present your calculated data in a table grouped by month. All you need to do is calling the sheet method and tell where to find the key (month) and where to find the value.
- Group changes
phpReport monitors as much groups as you like. As soon as a value changes phpReport executes certain actions like calling group header and group footer methods. See actions section for more details. To let phpReport know which attributes or elements should be monitored call the group method once for for each group. Out of the box phpReport offers group counters which lets you know how often a certain value (or group) occurs in an other group.
- Prototyping
Beginners and experienced users of phpReport can benefit from the prototype system. Prototying lets you know which method would habe been called, what data row triggered the actions, what are the values of the group fields and the values of aggregated fields. [Prototyping](prototype.rst)
Actions¶
Before we start to learn any details about using phpReport we need to know something about actions.
Calling the run() method starts the execution and phpReport takes control over the program flow. Whenever an important event occurs an action might be exectued.
Typical actions are:
call a method in the target object (The target parameter of the report class)
append a string to the output
execute a callable
call a method in the prototyp class
Within the configuration file you can specify exactly what action will be executed. During instantiation of the report class you might replace some of the configuration parameters.
Events like a group change will trigger an individual groupHeader action for defined groups. To be able to execute different action types the group() method also allows replacing the default action.
The default rules are simple: 1) If action is a string this string will be appended to $output. 2) If action is a method name the method will only be called when the method exist. The returned value will be appended to $output. 3) If action is a callable the returned value will be appended to $output.
The above rules can be altered by calling the setCallOption().
Named events¶
Each named event is mapped to an action. Below all events are listed. Parameters passed to the action object are shown in parenthesis.
Data independent events¶
These methods are called even when no data are provided.
init()¶
First event. Use to initialize application properties independent from the __construct method.
close()¶
Last event. Use to clean up the dishes independent from __destruct method.
totalHeader()¶
Called once to build the total header page of the report.
Data driven events¶
noData()¶
This event only occurs when the given data set is empty. In this case the following events will never be raised.
groupHeader($groupValue, $row, $rowKey, $dimID)¶
Raised when group values between two rows are not equal. Each group has its own groupHeader.
Group headers are executed from the changed group level down to the lowest declared group (within an data dimension).
After executing all headers the detail event will be performed.
- param mixed $groupValue
The current group value.
- param array|object $row
The current row which triggered the group change.
- param mixed $rowKey
The rowKey is the key of the current row taken from the input data set or given by calling the next() method.
- param int $dimID
The current data dimension. Initial data dimension equals 0.
detail($row, $rowKey)¶
Executed for each row of the last data dimension. When the row triggered a group change then the related group footers and group headers will be called before.
- param array|object $row
The current row.
- param mixed $rowKey
The rowKey is the key of the current row taken from the input data set or given by calling the next() method.
Methods for multi dimensional data¶
Following events belongs only to data sources having joined data.
noData_n($dimID)¶
Called when the declared source for the next data dimension doesn’t return any data. :param int $dimID: The ID of data dimension not having related data.
detail_n($row, $rowKey)¶
Except for the last dimension this event is raised for each data row (See detail method).
When group(s) are declared for this data dimension consider using groupHeader and groupFooter methods instead.
- param array|object $row
The current row.
- param mixed $rowKey
The rowKey is the key of the current row taken from the input data set or given by calling the next() method.
noGroupChange_n($row, $rowKey)¶
Raised when for a data dimension group(s) are declared but current row has the same group values than previous row. In a well designed data model this should not happen. If you can’t change the model consider what you have to do in such situations. Ignoring this case, trigger a warning or throw an exception are valid options.
- param array|object $row
The current row which triggered the group change.
- param mixed $rowKey
The rowKey is the key of the current row taken from the input data set or given by calling the next() method.
Prototyping¶
Before you start writing any code you might want to use the prototyping system to generate a report which shows some data of the currently processed row, names of methods which will be called in real life applications, the value of group fields and some values out of the aggregated fields.
Prototype tells also what the real action would be (e.g. Call method xy or append string ‘foobarbaz’).
It’s also a good idea to use prototyping before you start tracing or debugging your application.
You can call the prototype function at any time by just calling
$rep->prototype();
This will return an html table for the current action key.
The other way is setting the call method parameter by calling the setCallAction() method with one of the following constants as parameter.
- CALL_EXISTING = 0
Call methods in owner class only when implemented. Default.
- CALL_ALWAYS = 1
Call also not existing methods in owner class. This allows using magic function calls.
- CALL_PROTOTYPE = 2
Call methods in prototype class when they are not implemented in owner class. Very useful for incremental developing of reports.
- CALL_ALWAYS_PROTOTYPE = 3
Call methods in prototype class for any action.
Usually the method is called once before calling the run() method. But it is also possible to alter the call action at any time.
// $rep has a reference to phpReport object
$rep->setCallAction(Report::CALL_EXISTING);
$rep->setCallAction(Report::CALL_ALWAYS);
$rep->setCallAction(Report::CALL_PROTOTYPE);
$rep->setCallAction(Report::CALL_ALWAYS_PROTOTYPE);
The prototying class is a good example how flexible a report can be.
Configuration¶
phpReport lets you configure the real action to be performed for events which triggers one or more actions.
Whenever an event occurs the action defined to an action key will be performed.
For each possible action to be executed you can declare what should be done. Each action key has a default action assigned. Within the config.php file the default actions might be adjusted to meet your personal favorites or to follow business rules of your orgisation.
Action typ |
Action defined by |
---|---|
Call a method in target class |
Action is a legal method name |
Call a method in any class |
Action is an array ([class, method]) |
Ouput a string |
Action is not a legal method name or begins with an : |
Throw an error |
Action begins with error: |
Raise a warning |
Action begins with warning: |
Do nothing |
Action equals false |
The following table lists all possible actions, assigned defaults and notices how the % sign the will be replaced during run time.
Action mapping¶ action key
default value
% replaced by
init
init
close
close
totalHeader
%Header
$grandTotalName
totalFooter
%Footer
$grandTotalName
groupHeader
%Header
group name orgroup levelgroupFooter
%Footer
group name orgroup leveldetail
detail
noData
<br><strong>No data found </strong><br>
noData_n
noDataDim%
dimension id
noGroupChange
error:Current row in dimension % didn’ttrigger a group change.dimension id
Next to the actions parameter you can also declare the following parameters:
-
property
grandTotalName
¶ The name for the grand total group. Will also be used to build actions for action keys totalHeader and totalFooter.
Note
You can always access grand totals by group level of 0.
-
property
buildMethodsByGroupName
¶ When true the % sign actions related to groupHeader and groupFooter will be replaced by the group names. When false by the numeric group level.
That’s the place where you define the type of actions to be performed or the method names.
Actions have a key which will translated to real action names.
Per default the action ‘init’ will call a method called ‘init’. That’s fairly simple. The same is true alse for the ‘detail’ and ‘close’ actions.
The deaufault action ‘totalHeader’ is ‘%Header’. The % sign will be replaced by the value of the ‘grandTotalName’. Assuming ‘grandTotalName’ is unchanged and has the value of ‘total’ the action to be performed is the ‘totalHeader’ method. The same rule applies to the ‘totalFooter’ action.
Similar rules are true for the ‘groupHeader’ and ‘groupFooter’ actions. But as we need an action for each defined group the % sign will be replaced by the group name. Example: You defined group changes for ‘region’. ‘customer’ and ‘invoice’.
region regionHeader regionFooter customer customerHeader customerFooter invoi invoiceHeader and invoiceFooter
You like it the other way. Then name the groupHeader action ‘head_%’ and footerAction ‘foot_%’.
region head_region foot_region customer head_customer foot_customer invoice head_invoice foot_invoice
The same rule with ‘buildMethodsByGroupName’ set to ‘ucfirst’ will result in these actions: region head_Region foot_Region customer head_Customer foot_Customer invoice head_Invoice foot_Invoice
The rules above are very simple to follow so that’s nothing really sopisticated.
Setting the ‘buildMethodsByGroupName’ set to ‘false’ will replace the % sign by the group level. The last example would call those methods
region head_1 foot_1 customer head_2 foot_2 invoice head_3 foot_3
What might look very strange at the first sigth is very powerful when you want to write very flexible apps. Changing the second group from ‘customer’ to ‘branch’ doesn’t change the action group names. While knowing that the group value is passed to the method as a parmeter and that you have easy access to the group names gives you nearly unlimited choices.
Your are not limited to declare how method names are build.
For some actions it is suitable to define a string. Then the string will be appende to the $output variable. A good example is the ‘noData’ action. In many cases you won’t instantiate phpReport when your data query doen’t return any data. But you might also in this cases a report with nice header and footer and in between just printint a message like “Sorry, we couldn’t find any data”. So it’s not worth to create a method in each report which returns such a string. The solution is to declare this string as a default. A : sign at the beginning makes sure that this string is always treated as a string and can not be mixed up with a method name.
The % sign in ‘noData_n’ actions will be replaced by the number of current dimension when the current dimension is greater than 0. See multi dimensional data for more details.
The very last parameter is called ‘userConfig’. This is an optional way how you can pass data around. phpReport isself does’t use this values.
Note
All directives can be altered when initializing a new phpReport. Some even when calling a method.
Data input¶
Data input is completely decoupled from your application. Use your own data access methods, data models and components as well as data access features from any PHP framework or ORM (Object Relation Mapper).
phpReport accepts data rows being an array, on object or even a string. These data rows can be passed to phpReport all at once, row by row or in batches of any size. This gives greatest flexibility and more control over memory usage when working with large amount of data.
Choose the access strategy which seems most suitable for your current application and change this strategy on demand without touching the application.
Between reading and feeding data to phpReport you can modify or filter the input. So it’s easy to work with any data format (like csv files, excel sheets and json strings).
phpReport accepts data in three different ways.
- Passing all data within an iterable to the run() method.
phpReport iterates over the data set and calls the next() method for each entry.
- Passing chunks of data within an iterable by calling the run()
method for each chunk while setting the parameter finalize to false or by calling the nextSet method. phpReport iterates over the data set and calls the next() method for each entry. To finalize the job either call the end() method after the last chunk or set the finalize parameter for the last chunk to true.
- Passing single rows by calling the next() method for each data row. This
is in many cases the most efficent way as you don’t have to collect your data into an array. To finalize the job just call the end() method after processing the last row.
Joining Data¶
Joining data in phpReport can be used for different pupurses.
First you can join any data row with any other source. Data sources don’t have to be the same kind. So you can for example easily combine a row from a database with rows from an excel sheet. Use the same data input methods for joined data as for the primary data.
Another way to join data comes into place when your data row is a data model. This model usually has methods or properties providing related data. Declare the relationship by calling the join() method and phpReport will iterate over these related data.
To iterate over an multi-dimensional array the join() method is used to declare which array element holds the next dimension.
To the application joining data is largely invisible. Grouping and computing values behave like data would have been served as a flat record.
-
join($value, $noDataAction, $dataAction, $noGroupChangeAction, ...$params): Report
- Parameters
$value (mixed) – The source for the joined data. When source is a callable just return the whole the data set or return false and call the nextSet() method or the next() method for each data row.
$noDataAction (mixed) – The action to be executed when $source doesn’t return any data.
$dataAction (mixed) – The action to be executed for each row returned by $source.
$noGroupChangeAction (mixed) – The action to be executed when two consecutive rows don’t trigger a group change.
$params (mixed) – Variadic parameters to be passed to $source.
Data output¶
The basic idea behind data input is also true for data output. phpReport doesn’t create any output itself.
Actions described before are the places where you can build your output. Using external components like mpdf, tcpfd, phpSpredsheet, PHPWord will help to format the output as you like.
phpReport assists you collecting your output by appending the return values of the action methods or defined action strings to the $output property.
$output is used for nothing else. So you can
Alter the content
Write content to disc
Delete content
Append data to content
…
Your action methods don’t need to return anything. You can also keep desired output in any other variable.
Note
$content will be returned from the run() and the end() method.
Group changes¶
Compexity in applications usually grows exceptionlly with every addidtional group which needs to be managed.
With phpReport you only need to call the group() method once for every group. Groups can be controlled in every data dimension. Just call the group() method after calling the related data() method.
A group change occurs when within a data dimension when group values of the previous row don’t equal those of the current row.
Tip
Data don’t need to be sorted by groups. But make sure that rows are grouped by the group field or you might raise unwanted group changes.
Once a group change has been detected the appropiate action methods (group headers and group footers) will be executed.
-
group
($name, $value = null, $headerAction = null, $footerAction = null, ...params)¶ Declare a data group.
- Parameters
$name (string) – The name to be used for this group. This name will be used to build method names for group headers and footers (depending on configuration parameters). Must be unique between all dimensions. All group related values (including cumulated values from sum or sheet methods as well as row and group counters) can be retrieved by this group name or the group level.
$value (mixed) – Source of the group value. Use the attribute name when data row is an object or the key name when data row is an array. It’s also possiblbe to use a callable (a closure or an array having class and method parameters) expecting $row and $rowKey as parameters. When the $value parameter is null it defaults to the content of $name parameter.
$headerAction (mixed) – Set individual group header action. Null to execte the default action. False to deny any action.
$footerAction (mixed) – Set individual group footer action. Null to execte the default action. False to deny any action.
$params (mixed) – Variadic parameters to be passed to callables declared with value parameter.
- Returns
$this which allows method call chaining.
Example
$rep = (new Report ($this))
->group ('region')
->group ('year', fn($row) => substr($row->saleDate, 0, 4))
->group ('month', fn($row) => substr($row->saleDate, 5, 2))
->group ('customer', 'customerID', null, '</table>')
The above example declares four groups (group level 1 to 4) to be monitored. Instead of executing the customer footer action the string ‘</table>’ will be appended to the $output property.
Note
Group level 0 is always the top level which is called grandTotal.
For each declared group a group counter will be instantiated and incremented when a group change occurs. See ‘Calculation’ for details.
Aggregation¶
Collector¶
A collector class is designed to hold and manage multiple items. An item can be an other collector or an calculator object.
The main responsibilty of an collector is to call methods in assigned items. To make sure that the cumputation of calculated values works correct calculator objects must be registered to the total collector or to one of his child collectors.
The collector class has the ArrayAccess interface and the magic __get method implemented which allows a broad range of access options.
The visibility of the $items array is public. This allows maximum speed when accessing an item and gives the opportunity to apply all php array methods.
Add items¶
Items will be added (or registered) to an collector usually by calling the calculate() or sheet() methods of the phpReport class.
You may can also add items by the addItem() method. This is especially desired when you want to group multiple item objects.
Adding items to a sheet collector is hidden and will be internally handled based on key values of the add() method.
Alternate item keys¶
Items are stored in the $item array indexed by the name given when calling the addItem() method. You can also apply an alternate key to allow accessing an item by the alternate key as well.
The setAltKeys() method will set many alternate keys while the setAltKey() method one alternate key.
The group conter collecor uses alternate keys to allow accessing the counters by the group level and by the group name.
Get items¶
To access an item you can use the getItems() method for all items or the getItem() method to get one item.
The magic __get() and the array access get methods calls the getItem() method. The item will returned when it exist either by the item array key or by the alternate key.
$this->rep = new phpReport($this);
$this->rep->compute('sales');
// All of the following statements will return the same item.
$item = $this->report->total->getItem('sales');
$item = $this->report->total->items['sales']);
$item = $this->report->total->sales;
$item = $this->report->total['sales'];
Aggregate methods¶
All aggregate methods implemented in the calculator classes have their counterpart it the collector classes.
The collector aggregate methods calls the same methods for each assigned item. Returned results will be returned either as an array indexed by the item key or as an scalar aggregated value.
Subset of items¶
To apply aggregate methods only on some items you can build a subset by calling the following filter methods. Each of them will return a cloned collector object with just the filtered items.
To use the cloned collector multiple times hold the reference to the cloned collector in a variable.
-
range(...$ranges): AbstractCollecotor
Extract ranges of items.
Returns ranges of items located between start and end keys.
When a range is an array value1 is the start and value2 the end key. When one of the keys don’t exist the value of the altKey will be used instead. When the items still doesn’t exist an error will be thrown.
If start key equals Null the range begins at the first item. When the end key equals Null the range ends at the last item.
When a range is not an array then the item with the corresponding key or altKey is returned if it exist. If this doesn’t exist php raise a notice.
Item keys are preserved. Sort order within ranges are preserved. Ranges are returned in given order. When items belong to multiple ranges only the first occurence will returned.
:param array|int|string[] $ranges Ranges or item keys for items to be filtered. :return AbstractCollector Cloned collector with items in ranges. :throws InvalidArgumentException When start or end item doesn’t exist.
-
between(...$ranges): AbstractCollecotor
Filters items where key is between values.
Iterates over each collector item. If a range is an array and the item key is between value1 and value2 of this range (inclusive) the item is returned.
If the range isn’t an the item with the corresponding key is returned.
If a range matches the key of a named range then the named range value will be used to filter the items.
Item keys and sort order are preserved.
- Parameters
array|int|string[] – $ranges Ranges or item keys for items to be filtered.
- Returns
AbstractCollector Cloned collector with items in ranges.
-
filter(callable $callable):
Filters items using a callback function. Iterates over each item in the array passing key and value to the callback function. If the callback function returns TRUE, the current item is returned into the cloned collector. Item keys are preserved.
- Parameters
$callable (callable) – The callback function to use.
- Returns
AbstractCollector Clone of current collector with filtered items
-
cmd(callable $command, ...$params): AbstractCollector
Alter item collection by executing a php array command.
- Parameters
$command (callable) – Any php array command which accepts an array as the first parameter.
$params (mixed[]) – Additional parameters passed to the php command.
- Returns
AbstractCollector Clone of current collector with applied command on the items array.
Calculator¶
phpReport comes with 3 different calculator classes. The reason behind is that only nessessarty operations will be performed.
In most cases you don’t need the minimum or maximum value of an attribute. Identifying those values is time consuming. The same is true for the number of rows having a not null or a not zero value.
- The classes provided are:
CalculatorXS (default)
Calculator
CalculatorXL
The CalculatorXS class has the minimum functionality. It’s perfect to cumulate any value or to increment any counter. To increment a value (or better a counter) just call the inc() method. It’s the same as calling add(1) method.
The Calculator class don’t have the incrememt method but counts the not null and not zero values.
The CalculatorXL class extends the Calculator class and detects the minimum and maximum values of an attribute. Use the min() and max() methods to get these values.
The aggregate() method instantiates a calculator object which provides aggregate functions. The sheet() method instanditates a sheet colletor which holds many calculator objects.
Example
$rep = (new Report ($this))
->data('object')
->aggregate ('amount')
->aggregate ('price', fn($row, $rowKey) => $row->amount * $row->pricePerUnit);
Sheet¶
Aggregate values in an tabular form like in a spreadsheet.
Sometimes a sheet can eliminate the need for declaring a group or a data dimension. You can also aggregate the same value in different sheets so that results are grouped by different keys.
The sheet() method instantiates a Sheet or a FixedSheet object. Both of them are special variants of the collector object and will be assigned to the total collector ($total).
For each column in a sheet a calculator object will be instantiated and linked via the $items array property.
Note
All calculator objects within a Sheet or FixedSheet object are of the same type.
Group levels are like sheet rows and data keys like sheet colums.
-
sheet
(string $name, $value, $headerAction = null, $footerAction = null, ...$params) Aggregate attributes in a sheet.
Sheet is a collection of calculators for a horizontal representation of a value. Call this method once for each sheet.
- Parameters
$name (string) – Unique name to reference the sheet object. The reference will be hold in $this->total.
$value (mixed) –
Source of the key and value to be aggregated. Must be served in an array with only one entry were key is the array key and value the value.
Key and attribute name are attribute names when data row is an object or or when row is an array the element keys. It’s also possiblbe to use a closure which returns an array [key => value]. False to just instantiate and reference the sheet. To execute the calculation call the add() method of the sheet object. This is very useful when getting the key or value to be calculated is complicated and / or you need these data on the detail level.
Tip
Using the array_column function might declaring the latest data dimension redundant.
$typ (int|null) – The calculator type. Typ is used to choose between a calculator class. Options are XS, REGULAR and XL. Defaults to XS. Typ belongs to all sheet items.
$fromKey (mixed) – To use a fixed sheet declare the first calculator name. Pass an array when sheet names are not in an sequence. Example: [‘young’, ‘mid-aged’, ‘old’l Null for sheets where calculators are instantiated for each key value.
$toKey (mixed) – The last calculator name for fixed sheet. FromKey will be icremented until $toKey is reached.
$maxLevel (int|null) – The group level at which the value will be added. Defaults to the maximum level of the dimension. Might be less when aggregated data are only needed on higher levels.
$params (mixed) – Variadic parameters to be passed to callables declared with value parameter.
- Returns
$this which allows method call chaining.
FixedSheet class¶
FixedSheet classes are best used when you know which columns you need and want them to be instantiated all at once. To do so pass an array of column names or the starting and ending name to the sheet() method. When starting name is a string make sure that the ending name can be reached by incrementing the starting name.
$rep = new Report ($this);
// Declare season names as columns
$rep->sheet ('sales', ['regionID' => 'amount'], ['spring', 'summer' ,'autumn', 'winter'])
// Declare columns 1 to 12 (e.g. to represent month)
$rep->sheet ('sales', ['regionID' => 'amount'], 1, 12)
// Declare columns a, b, c, d, e and f
$rep->sheet ('sales', ['regionID' => 'amount'], 'a', 'f')
When you try to add a value to an not existing column an exception will be thrown.
Sheet class¶
Sheet classes don’t have a fixed number of columns. Columns will be instantiated whenever a data row delivers a new column name.
If you need columns in a sorted order you should sort your data accordingly. If this in not suitable ksort the $items property of the sheet object.
$rep = (new Report ($this))
->data('array')
->sheet ('sales', ['regionID'=> 'amount'])
phpReport manages aggregation by using calculator classes organized in collector classes.
Three different calculator classes provides a different set of aggregation methods. Sheets are special variants of an collector. They are used to hold multiple calculator ojects of the same type.
Getting values¶
Almost all methods which initializes an phpReport applicaton have a parameter called value. Of course you shouldn’t pass a real value but the information where to find the value.
The following table shows all options and the differences between objects and arrays.
Value sources¶ value
row is an array
row is an object
string or integer
value of $row[$value]
value of $row->$value
closure
Returned value of closure
Returned value of closure.
Array with one element
Returned value of $value method in target class
Returned value of $value function in row object.Only $params will be passed to the function.Array with two elements
Returned value of callable.When first element is a classname it is a static call.Same as for arrays:
When the value source is a closure or a callable the variadic parameters will also passed to the method.
Methods returning information¶
The report class has some extra convenience methods to provide you with useful information.
-
class
Report
¶ The report class offers a lot of methods which delivers almost all information you need to create your application.
-
getRow
(int $dimID = null)¶ Get the active row for the requested dimension.
- Parameters
$dimID (int|null) – The data dimension for which you want the current row. Defaults to the current data dimension. If $dimID is negative the value will be subtracted from the current data dimension.
- Returns
The active data row for the requested dimension.
-
getRowKey
($dimID)¶ Get key of the active row for the requested dimension.
- Parameters
$dimID (int|null) – Same as in getRow().
- Returns
The requested key.
-
isFirst($level = null): bool
Checks if the current group is the first one within the next higher group. e.g. Is it the first invoice for a customer.
- Parameters
$level (string|int|null) – The group level to be checked. Defaults to the next higher group level.
- Returns
True when the current group is the first one within the givel level. False when not.
-
isLast($level = null): bool
Check if the current group footer action is executed the last time within the group level. The question can only be answered in group footers.
- Parameters
$level (string|int|null) – The group level to be checked. Defaults to the next higher group level.
- Returns
True when the current action is executed the last time within the given group level. False when not.
- Throws
InvalidArgumentException when method is not called in a group footer or asked for group levels not higher than the current one.
-
getLevel($groupName = null): int
Get the current group level or the level associated with the group name.
- Parameters
$groupName (string|null) – The name of the group. Null for the current group level.
- Returns
The requested group level
-
getGroupValues(?int $dimID = null, bool $fromFirstLevel = true): array
Get all active group values. Note that in footer methods the row which triggered the group change is not yet active.
- Parameters
$dimID (int|null) – The dimension id for / till the group values will be returned. Defaults to the current dimension id.
$fromFirstLevel (bool) – When true all group values from the first dimension to the requested dimension are returned. When false only the group values of the requested dimension are returned.
- Returns
Array with requested group values indexed by group level.
-
getGroupValue
($group = null)¶ Get the current value for the requested group.
- Parameters
$group (int|null|string) – String representing the group name or integer representing the group level. When null it defaults to the current group level. Negative values are substracted from the current level.
- Returns
Current value of the requested group.
-
getGroupNames(): array
Get all group names.
- Returns array
Array of all group names.
-
getGroupName(int $groupLevel): string
Get the associated group name of the group level.
- Parameters
$groupLevel (int) – The level of the group.
- Returns string
The associated group name of the level.
-
getDimId(mixed $level): int
Get the dimension ID for a given group level.
- Parameters
$groupLevel (mixed) – The level of the group. Defaults to the current level.
- Returns int
The dimension id.
-
Overview of methods and properties¶
Methods to instantiate report class¶
data
Describe data input
group
Declare a group to monitor changes between data rows
aggregate
Declare variable to provide aggregate functons (sum, count, min, max)
sheet
Declare variable to be aggregated horizontally (having key and value)
Methods for data handling¶
run
Start execution with data
runPartial
Iterate over a set of data
next
Take a single data row
end
Finalize execution
Action methods called from report class¶
init
First called method to initiialize application
close
Last called method to clean up the dishes independent from __destruct method.
totalHeader
Called once after init() to build the total header page of the report.
totalFooter
Called once before close() to build the total footer page of the report.
groupHeader
Called for each new group value(s)
groupFooter
Called after detail() but before activating new group value(s).
detail
Called for each data row in last data dimension.
noData
Called when no data was given.
noData_n
Called when no data was given for dimension ‘n’.
noGroupChange_n
Called when groups for dimension ‘n’ are declared but row didn’t trigger a group change.
Methods returning information¶
getRow
Get the active row for the requested dimension.
getRowKey
Get the key of active row for the requested dimension.
getGroupNames
Get names for all declared groups.
getGroupName
Get name for a requested or current group level.
getGroupValues
Get current values for all declared groups.
getGroupValue
Get current value for the requested or current group.
getLevel
Get the current group level or the level associated with the group name.
getChangedLevel
Get the level which triggered the group change.
getDimID
Get the dimension id related to a group level or the current dimension id.
isFirst
Bool if the action for the current or given level called the first time.
isLast
Bool if the action for the current or given level called the last time.
Public Properties¶
- $output
String with concatenated return values from actions
- $gc
Group count collector
- $rc
Row count collector
- $total
Collector for calculators, sheets and collectors
- $userConfig
Configuration parameter given during instantiation
Prototyping methods¶
prototype
Call prototype method realted to current action.
setCallAction
Alter targets for actions to be executed.