I have the following class hierarchy:
interface IReportGenerator {
public function setTitle ($title);
public function setColumns ($columns);
public function setPrintArea ($start, $stop);
public function setPageOrientation ($value);
public function createReport ($data);
public function saveReport ($name, $path = null);
public function saveReportAs ($name, $path = null, $type = null);
}
abstract class AbstractReportGenerator implements IReportGenerator {
public function __construct() {
$this->report = new PHPExcel();
}
public function setTitle ($title, $now = false) {
// store
return $this;
}
public function setColumns ($columns) {
// store
return $this;
}
public function setPaperSize ($value, $now = false) {
// store
return $this;
}
public function setPageOrientation ($value, $now = false) {
// store
return $this;
}
public function setPrintArea ($start, $stop, $now = false) {
// store
return $this;
}
public function saveReport ($name, $path = NULL) {
return $this->saveReportAs($name,$path,self::EXCEL_2007);
}
public function saveReportAs ($name, $path = NULL, $type = NULL) {
// save report
return $this;
}
public function createReport ($data) {
$this->doHeader();
$this->doTitle();
$this->doColumnHeaders();
$this->doData($data);
$this->doFooter();
$this->doFormatting();
$this->doMargins();
$this->doPrintOptions();
}
abstract protected function doHeader();
abstract protected function doTitle();
abstract protected function doColumnHeaders();
abstract protected function doData($data);
abstract protected function doFooter();
abstract protected function doFormatting();
abstract protected function doMargins();
abstract protected function doPrintOptions();
}
class ReportGeneratorSimple extends AbstractReportGenerator {
public function __construct() {
parent::__construct();
}
protected function doHeader () {
// do nothing
}
protected function doTitle () {
echo 'title A';
}
protected function doColumnHeaders () {
echo 'column A';
}
protected function doData ($data) {
echo 'data A';
}
protected function doFooter () {
// do nothing
}
protected function doFormatting () {
echo 'format A';
}
protected function doMargins () {
// do nothing
}
protected function doPrintOptions () {
// do nothing
}
}
class ReportGeneratorFormatted extends ReportGeneratorSimple {
public function __construct() {
parent::__construct();
}
protected function doHeader () {
parent::doHeader();
}
protected function doFooter () {
parent::doFooter();
}
protected function doFormatting () {
parent::doFormatting();
echo 'format B';
}
}
When I do:
$report = new ReportGeneratorFormatted();
$report->setTitle('title');
$report->setColumns($columns);
$report->createReport($data);
$report->saveReport('file.xlsx');
The output i get is (in no particular order):
'data A'
'format A'
Any idea why 'title A', 'columns A', and 'format B' are not printing? The saveReport() and saveReportAs() methods are working as well.
#zerkins - You are correct, the code I supplied runs as expected. The results I supplied came from the production code, not the sample.
Given that the sample worked correctly, it was as simple as tracking down the difference in the production code. It turned out to be a missing call to "parent" in one of the child classes.
Thanks!
Related
I wanna create class for making fields, but in Laravel Nova this classes called like Text::make()->placeholder() and etc. This means that methods inside that class is static.
This is my field class:
class Field
{
private $field = [];
public function set($key, $value)
{
$this->field[$key] = $value;
}
public function get()
{
return $this->field;
}
}
class Text
{
private static $field;
public static function make($name)
{
self::$field = new Field;
self::$field->set('#saturn_type', 'string');
self::$field->set('#saturn_key', $name);
self::$field->set('#saturn_field', 'text');
return new Text;
}
public function placeholder($value)
{
self::$field->set('placeholder', $value);
return $this;
}
public function required()
{
self::$field->set('required', true);
return $this;
}
public function translate()
{
self::$field->set('translate', true);
return $this;
}
public function wysiwyg()
{
self::$field->set('wysiwyg', true);
return $this;
}
public function get()
{
return (array) self::$field->get();
}
}
and this is how i call it:
$fields = [
Text::make('name')->placeholder('Full Name'),
Text::make('email')->placeholder('Email'),
Text::make('password')->placeholder('Password'),
]
$lastArray = $fields->map(function ($field) {
return $field->get();
}
);
But when i call get() method for each item in this array to get array, each item returns the last item's name and placeholder because it is static. How can i solve this.
I found the solution. Actually my friend Nijat found ))
class Field
{
private $field = [];
public function set($key, $value)
{
$this->field[$key] = $value;
}
public function get()
{
return $this->field;
}
}
class Text
{
private $field;
public function __construct($name)
{
$this->field = new Field;
$this->field->set('#saturn_type', 'string');
$this->field->set('#saturn_key', $name);
$this->field->set('#saturn_field', 'text');
}
public static function make($name)
{
return new Text($name);
}
public function placeholder($value)
{
$this->field->set('placeholder', $value);
return $this;
}
public function required()
{
$this->field->set('required', true);
return $this;
}
public function translate()
{
$this->field->set('translate', true);
return $this;
}
public function wysiwyg()
{
$this->field->set('wysiwyg', true);
return $this;
}
public function get()
{
return (array) $this->field->get();
}
}
You just have to create constructor then call it in static method.
You can make Text inherit from Field and have a much simpler make method:
class Field
{
public static function make(...$arguments)
{
return new static(...$arguments);
}
// ...
}
This will instantiate the parent class (e.g. Text) and return it, allowing you to keep the chaining. In the methods you can then use $this-> as usual (instead of self::). And move the content of Text::make to the constructor:
class Text extends Field
{
public function __construct($name)
{
$this->set('#saturn_type', 'string');
$this->set('#saturn_key', $name);
$this->set('#saturn_field', 'text');
}
// ...
}
I am new in codeigniter.
I need to do the following code in utility.php which is a custom library.
class Utility{
public $x=test("123");
public function test($name)
{
return $name;
}
echo $x;
}
Thanks in advance
This is showing syntax error.
Maybe this way?
class Utility
{
public $x;
public function __construct($name = 'default name')
{
$this->x = $this->test($name);
}
public function test($name)
{
return $name;
}
}
Then in controller you would go with
class Welcome extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
public function index($name = null)
{
$this->load->library('utility', [$name]);
echo $this->utility->x;
}
}
I am trying to create a library for codeigniter that uses pthread, everything works fine but when i want to assign a value to an array this don't work with traditional $a['key'] = 'val';
Small Test Exemple : ( updated )
class Test {
protected $core;
protected $stack;
public function init(){
$this->stack = new Test_Stack();
$this->core = new Test_Core($this->stack);
}
public function do_test(){
return $this->core->assign();
}
}
class Test_Stack extends Stackable {
protected $a;
function __construct(){
$this->a = array();
}
protected function test(){ // Call from other class extends Threads
$this->a['key1'] = 'NOWORK';
print_r($this->a); // THIS RETURN NOTHING
$this->a = array_merge($this->a, array('key1' => 'WORK'));
print_r($this->a); // NOW THIS GOOD RETURN Key1..
}
public function run(){}
}
class Test_Core {
protected $thread;
protected $stack;
function __construct($s){
$this->stack = $s;
}
public function assign(){
$this->thread = new Test_Thread($this->stack);
$this->thread->start();
$this->thread->join();
}
}
class Test_Thread extends Thread{
protected $stack;
function __construct($s){
$this->stack = $s;
}
public function run(){
$this->stack->test();
}
}
I write this basic code without testing but it's the same structure of my lib and need this to extends test_stack and add or change test function for exemple.
Even if works now, I would understand why I can't assign my array normally ?
Or rather, what am I doing wrong?
Working in Mine :
class Stack {
protected $a;
function __construct(){
$this->a = array();
}
function test(){
$this->a['key1'] = 'NOWORK';
print_r($this->a); // THIS RETURN NOTHING
$this->a = array_merge($this->a, array('key1' => 'WORK'));
print_r($this->a); // NOW THIS GOOD RETURN Key1..
}
}
$obj = new Stack();
$obj->test();
Output :
Array
(
[key1] => NOWORK
)
Array
(
[key1] => WORK
)
OK array isn't thread safe, should be used stackable, this do the trick :
Libraries/Test.php :
class Test {
protected $core;
protected $stack;
public function init(){
$this->stack = new Test_Stack();
$this->core = new Test_Core($this->stack);
}
public function do_test(){
$this->core->assign();
$this->core->assign();
$this->core->assign();
}
public function get_a(){
return $this->core->get_a();
}
}
class Test_Array_Stack extends Stackable {
public function run(){}
}
class Test_Stack extends Stackable {
protected function test($a){
$a[] = 'WORK';
}
public function run(){}
}
class Test_Core {
protected $thread;
protected $stack;
protected $a;
function __construct($s){
$this->stack = $s;
$this->a = new Test_Array_Stack();
}
public function assign(){
$this->thread = new Test_Thread($this->stack, $this->a);
$this->thread->start();
$this->thread->synchronized(function($thread){
$thread->wait();
}, $this->thread);
return $this->a;
}
public function get_a(){
return $this->a;
}
}
class Test_Thread extends Thread{
protected $stack;
protected $a;
function __construct($s, $a){
$this->stack = $s;
$this->a = $a;
}
public function run(){
$this->stack->test($this->a);
$this->synchronized(function($thread){
$thread->notify();
}, $this);
}
}
You can extends Test_Stack to create lib extension more useful for my project, like this on other file Test_Info.php :
require_once APPPATH.'libraries/Test.php';
class Test_Info extends Test {
function init(){
$this->stack = new Test_Info_Stack();
$this->core = new Test_Core($this->stack);
}
}
class Test_Info_Stack extends Test_Stack {
protected function test($a){
parent::test($a);
$a[] = 'INFO';
}
}
And usage on controller:
function index(){
//without extension
$this->load->library('Test');
$this->test->init();
$this->test->do_test();
print_r($this->test->get_a());
//with extension
$this->load->library('Test_Info');
$this->test_info->init();
$this->test_info->do_test();
print_r($this->test_info->get_a());
}
It took me some time, i hope it will help someone and LuckyBurger thank you for the explanation link.
I tried a code which I called a parent method in its daughter __construct and itreturns NULL,
I dont know why? I would be very happy if anyone could explain to me why.
Thanks in advance.
Here is my code
<?php
class me
{
public $arm;
public $leg;
public function __construct()
{
$this->arm = 'beautiful';
$this->leg = 'pretty';
}
public function setLeg($l)
{
$this->leg = $l;
}
public function getLeg()
{
return $this->leg;
}
}
class myBio extends me
{
public $bio;
public function __construc()
{
$this->bio = $this->setLeg();
}
public function newLeg()
{
var_dump($this->bio);
}
public function tryLeg()
{
$this->leg = $this->getLeg();
print $this->leg;
}
}
$mB = new myBio();
$mB->newLeg();
$mB->tryLeg();
?>
When I call:
$mB = new myBio();
$mB->newLeg();
, it returns
NULL,
BUT
$mB->tryLeg();
returns e string, 'pretty'.
You have a typo on this line:
$this->bio = $this->setLeg();
You're calling your setter, not your getter, and since the setter doesn't return a value you're getting null instead.
You've also misspelled construct:
public function __construc()
And you need to call the parent constructor.
<?php
class me
{
public $arm;
public $leg;
public function __construct()
{
$this->arm = 'beautiful';
$this->leg = 'pretty';
}
public function setLeg($l)
{
$this->leg = $l;
}
public function getLeg()
{
return $this->leg;
}
}
class myBio extends me
{
public $bio;
public function __construct()
{
parent::__construct();
$this->bio = $this->getLeg();
}
public function newLeg()
{
var_dump($this->bio);
}
public function tryLeg()
{
$this->leg = $this->getLeg();
print $this->leg;
}
}
$mB = new myBio();
$mB->newLeg();
$mB->tryLeg();
I have two Classes viz foo & Bar
class bar extends foo
{
public $element = null;
public function __construct()
{
}
}
and the Class foo goes as
class foo implements ArrayAccess
{
private $data = [];
private $elementId = null;
public function __call($functionName, $arguments)
{
if ($this->elementId !== null) {
echo "Function $functionName called with arguments " . print_r($arguments, true);
}
return true;
}
public function __construct($id = null)
{
$this->elementId = $id;
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->data[$offset]);
}
public function offsetUnset($offset)
{
if ($this->offsetExists($offset)) {
unset($this->data[$offset]);
}
}
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
$this->$offset = new foo($offset);
}
}
}
i want that when i run the below piece of code:
$a = new bar();
$a['saysomething']->sayHello('Hello Said!');
should return Function sayHello Called with arguments Hello Said! from foo's __call magic method.
Here, i want to say is saysomething should be passed in $this->elementId from foo's __construct function and sayHello should be taken as method and Hello Said should be taken as parameters for sayHello Function which would be rendered from __call magic method.
Also, need to chain methods like:
$a['saysomething']->sayHello('Hello Said!')->sayBye('Good Bye!');
If I'm not mistaken, you should change foo::offsetGet() to this:
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
return new self($this->elementId);
} else {
return $this->data[$offset];
}
}
It returns an instance of itself if there's no element at the given offset.
That said, foo::__construct() should be called from bar::__construct() as well and be passed a value other than null:
class bar extends foo
{
public $element = null;
public function __construct()
{
parent::__construct(42);
}
}
Update
To chain calls, you need to return the instance from __call():
public function __call($functionName, $arguments)
{
if ($this->elementId !== null) {
echo "Function $functionName called with arguments " . print_r($arguments, true);
}
return $this;
}