If I have this example :
class A {
public function test(){
echo 'a';
}
}
class B {
public function test(){
echo 'b;
}
}
class C {
public function test(){
(new A())->test();
}
}
(new A())->test();
(new B())->test();
(new C())->test();
I want to get array with all called functions and classes, something like:
[
'A' => [
'function' => 'test',
'count' => 2,
'miliseconds' => 20,
'miliseconds_each' => [5, 15],
],
'B' => [
'function' => 'test',
'count' => 1,
'miliseconds' => 25,
'miliseconds_each' => [25],
],
'C' => [
'function' => 'test',
'count' => 1,
'miliseconds' => 30,
'miliseconds_each' => [30],
]
]
Notice: I want solution for whole framework not just bad workaround for this small example.
I would do like this, Make a base class and extends to update your analysis.
<?php
class Base{
static $data;
public static function analysis(){
return this::data;
}
function update($function){
if(isset(Base::$data[$function])){
Base::$data[$function] = ['count'=>Base::$data[$function]['count']+1,'function'=>'test'];
}else{
Base::$data[$function] = ['count'=>1,'function'=>'test'];
}
}
}
class A extends Base{
public function test(){
$this->update('a');
echo 'a';
}
}
class B extends Base{
public function test(){
$this->update('b');
echo 'b';
}
}
class C extends Base{
public function test(){
(new A())->test();
}
}
(new A())->test();
(new B())->test();
(new C())->test();
print_r(Base::$data);
?>
I know you can update code to get miliseconds and miliseconds_each
Live demo : https://eval.in/879998
Related
In a BI project we have multiple reporter functionalities. So, we have defined some classes to implement this feature. This classes needs many attributes to chain and build complex queries to generate reports. Any other classes should set specific values for these attributes, to get reports from this class. Values of these attributes are Non-Dynamic. I don't use the database to store them.
Below codes are the current model i am using:
Report generator (Main class):
class Report
{
private $indicator;
private $ratio;
private $divider;
private $criteria;
private $plantation;
private $reporter;
public function reporter($reporter)
{
$this->reporter = (new Reporters())->get($reporter);
return $this;
}
public function plantation($plantationId)
{
$this->plantation = $plantationId;
return $this;
}
public function ratio($ratio)
{
$this->ratio = (new Ratios())->get($ratio);
return $this;
}
public function divider($divider)
{
$this->divider = (new Dividers())->get($divider);
return $this;
}
public function criteria($criteria)
{
$this->criteria = $criteria;
return $this;
}
public function get()
{
return $this->mocker();
}
}
Dividers Class:
class Dividers
{
public $dividers = [
'sum' => [
'name' => 'مجموع',
'alias' => 'sum',
],
'plantations' => [
'name' => 'مجموعه انتخابی',
'alias' => 'plantations',
'model' => Plantation::class
],
'operation_types' => [
'name' => 'نوع عملیات',
'alias' => 'operation_type',
'model' => OperationType::class
],
'planting_years' => [
'name' => 'سال زراعی',
'alias' => 'planting_years',
'model' => Planting_year::class
],
'crops' => [
'name' => 'انواع گیاهان',
'alias' => 'crops',
'model' => Crop::class
],
];
public function get($divider)
{
if(!array_key_exists($divider, $this->dividers)){
return false;
}
return $this->dividers[$divider];
}
}
Ratio Class:
class Ratios
{
public $ratios = [
'SUM' => 'انباشته',
'KILOGRAM' => 'کیلوگرم',
'HECTARE' => 'هکتار',
'RIALPERKILO' => 'ریال به کیلوگرم',
'MILIONRIALPERTON' => 'میلیون ریال بر تن',
];
public function get($ratio)
{
if(!array_key_exists($ratio, $this->ratios)){
return false;
}
return $this->ratios[$ratio];
}
}
So for using report generator i will use this method:
$report = (new Report())
->plantation(352)
->divider('sum')
->reporter('NetProfit', ['operation_type'=> 364])
->criteria([['criteriaType'=> 'human_resources', 'value'=> '256'],['criteriaType'=> 'human_resources', 'value'=> '326']])
->ratio('sum')
->indicator(324, 523, 632)
->get();
My question is: what is the best pattern to store this data objects to reduce human mistakes?
This is more of an opinion based answer, so I'll suggest what I do when I am using static values.
Declare class members as static and protected for variables.
Like in your question class Ratios { } is a static class
class Ratios{
protected static $ratios = [...];
public static function get($ratio)
{
if(!array_key_exists($ratio, self::$ratios)){
return false;
}
return self::$ratios[$ratio];
}
}
//Access the Ratios class with.
$val = Ratios::get($ratio);
This ensures that
the values won't change throughout the lifecycle of your request
Adds a layer of security.
Also maintains the source, i.e. no change will occur if you don't change the code.
Doesn't create a new Instance(new Ratios()) for getting static values and you have that memory edge.
Do the same with the class Dividers { }.
I don't know if this is the best practice, but i would make a separate directory called "constants" or "config" or something that seems intuitive to you, and add there files named like Class_Property.php that return the value of that property
For example, in you Ratios class:
class Ratios
{
public $ratios = require('config/Ratios_ratios.php');
public function get($ratio)
{
if(!array_key_exists($ratio, $this->ratios)){
return false;
}
return $this->ratios[$ratio];
}
}
And in config/Ratios_ratios.php:
<?php
return [
'SUM' => 'انباشته',
'KILOGRAM' => 'کیلوگرم',
'HECTARE' => 'هکتار',
'RIALPERKILO' => 'ریال به کیلوگرم',
'MILIONRIALPERTON' => 'میلیون ریال بر تن',
];
?>
Depending on how critical that data is, opt for require/require_once/include. This is done mainly to keep your class more skinny, separating the constants
I have a model like bellow:
class Book extends ActiveRecord
{
{ public function getDomain()
{
return $this->hasOne(Domain::className(), ['ID' => 'domainID']);
}
public function getOwnerPerson()
{
return $this->$this->hasOne(Person::className(), ['ID' => 'ownerPersonID']);
}
public function getCreatorUser()
{
return $this->$this->hasOne(User::className(), ['ID' => 'creatorUserID']);
}
public function getUpdaterUser()
{
return $this->$this->hasOne(User::className(), ['ID' => 'updaterUserID']);
}
}
I've created an object from Book model by follow:
$model=Book::find()->all();
when I use $model->domain, every thing is ok, but when I use $model->ownerPerson, it throws an error:
Object of class backend\models\Book could not be converted to string
what is the problem?
Remove the second $this.
return $this->$this->hasOne(Person::className(), ['ID' => 'ownerPersonID']);
to
return $this->hasOne(Person::className(), ['ID' => 'ownerPersonID']);
i'm using codeigniter for a website project. when i include a model, it will work as long as no function is implemented (except the constructor).
this configuration works:
class Xyz_model extends CI_Model {
function __construct() {
}
}
this doesn't:
class Xyz_model extends CI_Model {
function __construct() {
}
public function get_xyz() {
return [
"xy" => ["xy"],
"yz" => ["xy"],
"zz" => ["xy","zx","zy"]
];
}
}
there is not even an database access... and i have no clue why it is not working.
You are extending the core model class, but the child's constructor is being used in placed of the parents:
parent::__construct();
Add that to your models constructor.
use this
In model
class Xyz_model extends CI_Model {
function __construct() {
}
public function get_xyz() {
$array = array(
'xy' => 'xy',
'yz' => 'xy',
'zz' => array("xy","zx","zy")
);
return $array;
}
}
In controller
$new = $this->Xyz_model->get_xyz()
print_r($new);
so output will be
Array ( [xy] => xy [yz] => xy [zz] => Array ( [0] => xy [1] => zx [2] => zy ) )
How Could I make generalised function which are used by every Model and Controllers Using Component as well behaviour??
//your behavior
class TestBehavior extends CActiveRecordBehavior
{
public $a = '';
public $b = '';
public function getA(){
return $this->a;
}
public function getB(){
return $this->b;
}
...
}
//in your model
public function behaviors(){
return array(
'TestBehavior' => array(
'class' => 'TestBehavior',
'a' => 'value a ',
'b' => 'value b',
),
//one more behavior
);
}
...
// use model behavior:
echo $model->TestBehavior->getA();
// in controller you can use attachBehavior() it will be like:
$this->attachBehavior('TestBehavior', array(
'class' => 'TestBehavior',
));
Hope this help you.
As my title, I tried call that method but I got an error:
Fatal error: Call to a member function post() on a non-object in C:\xampp\htdocs\cifirst\application\modules\front\controllers\shopping.php on line 11
If I create a controller not in module, that method I can use very easy but in this case can not (everything code in method below can not run). This is my code:
public function add_to_cart() {
$data = array(
'id' => $this->input->post('productId'), // line 11
'name' => $this->input->post('productName'),
'price' => $this->input->post('productPrice'),
'qty' => 1,
'options' => array('img' => $this->input->post('productImg'))
);
$this->load->library('MY_Cart');
$this->cart->insert($data);
//redirect($_SERVER['HTTP_REFERER']);
//echo $_POST['productId'].'-'.$_POST['productName'];
}
And this code doesn't work too:
public function __construct() {
$this->load->library('cart');
$this->load->helper('form');
}
I'm using XAMPP 1.8.1, CodeIgniter 2.1.3 and newest MX. Please help me!
When you're using CodeIgniter functions outside of controllers, models, and views you need to get an instance of Codeigniter first.
class MyClass {
private $CI;
function __construct() {
$this->CI =& get_instance();
$this->CI->load->library('cart');
$this->CI->load->helper('form');
}
public function someFunction() {
$var = $this->CI->input->post("someField");
}
}
If you are calling:
$this->input->post('productId');
inside controller than the problem is with your constructor declaration or your class name
Your construct part should contain code like this:
Class Home extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->CI->load->library('cart');
$this->CI->load->helper('form');
}
public function add_to_cart()
{
$data = array(
'id' => $this->input->post('productId'), // line 11
'name' => $this->input->post('productName'),
'price' => $this->input->post('productPrice'),
'qty' => 1,
'options' => array('img' => $this->input->post('productImg'))
);
}
}
It will work fine if you are calling from helpers function or any other classes than you should do something like this:
function __construct()
{
parent::__construct();
$this->CI->load->library('cart');
$this->CI->load->helper('form');
$this->CI =& get_instance();
}
public function add_to_cart()
{
$data = array(
'id' => $this->CI->input->post('productId'), // line 11
'name' => $this->CI->input->post('productName'),
'price' => $this->CI->input->post('productPrice'),
'qty' => 1,
'options' => array('img' => $this->CI->input->post('productImg'))
);
}