I use hook mechanism in Codeigniter. The kind of hook is post_controller_constructor.
There is one private object inside class hook`s:
private $settings = array();
This object is filled after executing hook.
How I can get access to $settings from libraries CI and controllers?
Class:
<? class LCode_module
{
private $CI;
private $_default_lang = "en";
private $_sufixLangDefault = "_EN";
private $allowedLanguages = array();
private $_countryCurrent;
private $countries = array();
private $languages = array();
private $settings = array();
public function __construct()
{
$this->CI =& get_instance();
/* Load lists */
$this->CI->load->library('listdata');
$this->countries['country'] = $this->CI->listdata->country;
$this->countries['country_code'] = $this->CI->listdata->country_code;
$this->countries['country_lang'] = $this->CI->listdata->country_lang;
$this->languages = $this->CI->listdata->languages_sys;
}
public function route()
{
//Here I put data to $settings
}
}
Method route is init method in hook
At the end of constructor:
/* Add object of class to GI instance */
$this->CI->LCode_module = new stdClass;
$this->CI->LCode_module->settings = &$this->settings;
After I try to get data in controller:
$CI =& get_instance();
$c = $CI->LCode_module;
var_dump($c); // NULL
Use this as your class, I created a static option which you can use whenever you need:
<?php
class LCode_module
{
private $CI;
private $_default_lang = "en";
private $_sufixLangDefault = "_EN";
private $allowedLanguages = array();
private $_countryCurrent;
private $countries = array();
private $languages = array();
private $settings = array();
private static $instance;
private static $static_settings;
public function __construct()
{
$this->CI =& get_instance();
/* Load lists */
$this->CI->load->library('listdata');
$this->countries['country'] = $this->CI->listdata->country;
$this->countries['country_code'] = $this->CI->listdata->country_code;
$this->countries['country_lang'] = $this->CI->listdata->country_lang;
$this->languages = $this->CI->listdata->languages_sys;
self::$instance = &$this;
self::$static_settings = &$this->settings;
}
public function route()
{
//Here I put data to $settings
}
public static function getInstance(){
if (is_null(self::$instance)) { self::$instance = new self(); }
return self::$instance;
}
public static function settings($key = NULL){
$instance = self::getInstance();
if(is_null($key)) return $instance::$static_settings;
return (array_key_exists($key, $instance::$static_settings) ? $instance::$static_settings[$key] : null);
}
}
Then you just call
LCode_module::settings()
when you need to retrieve the settings
This does imply parallel singleton use, which isn't exactly best practice, but it should do the trick for now since hooks only get loaded once. I'm sure CI has a way of performing this, but I'm drawing a blank on it right now.
Related
Please, could you help me a bit with my problem?
I have class called Translateable and then clasess Article and Banner, which extend this class.
Problem occurs, when I do this:
$article = (new Article)->find(15);
$banner = (new Banner)->find(1);
$articleTrans = $article->trans(); // method trans is method from Translateable
When I call $article->trans(); I expect output like this:
App\Models\ArticleTrans
Article
but it return this:
App\Models\ArticleTrans
Banner
First row is ok, but the second one if bad and I don't know, how to solve this problem.
I need to have $instance stored as static property.
Could you give me you help?
class Translateable extends Model {
static $transLang = null;
static $transClass = null;
static $instance = null;
public function __construct(array $attributes = array()) {
static::$transLang = App::getLocale();
parent::$transClass = static::$transClass;
parent::$instance = static::$instance;
parent::__construct($attributes);
}
/**
* get items trans
*
* #param null $lang
* #return mixed
*/
public function trans($lang = null) {
if($lang == null) {
$lang = static::$transLang;
}
echo static::$transClass;
echo class_basename(static::$instance);
die();
}
public static function find($primaryKeyVal, $columns = []) {
$tci = new static::$transClass;
$item = static::withTrans()->where(static::$instance->getTable() . '.' . static::$instance->primaryKey, '=', $primaryKeyVal)->where($tci->getTable() . '.lang', '=', static::$transLang)->first();
return $item;
}
}
class Article extends Translateable {
static $transClass = 'App\Models\ArticleTrans';
public function __construct(array $attributes = array()) {
parent::$transClass = static::$transClass;
parent::$instance = $this;
parent::__construct($attributes);
}
}
class Banner extends Translateable {
static $transClass = 'App\Models\BannerTrans';
public function __construct(array $attributes = array()) {
parent::$transClass = static::$transClass;
parent::$instance = $this;
parent::__construct($attributes);
}
}
in this below class i want to use class like with static methods and for use class methods without create new object from parent.
for example:
<?php
class Permission
{
protected $permission = false;
protected $id = 0;
public static function __construct()
{
return new static;
}
public function user( $id )
{
$this->id = $id;
}
public function check()
{
$this->permission = true;
}
public function item( $item )
{
return $item;
}
}
$bar = Permission::user(100)->item("HELLO");
print_r($bar);
this code not working and have problem. how to resolve this class problem?
That will not work because user method is not static, try changing this two methods, and this is good way of generating objects
public function __construct($id)
{
$this->id = $id;
}
public static function user( $id )
{
return new static($id);
}
I'd suggest you a singleton pattern, like this
class Permission
{
static protected $permission = false;
static protected $id = 0;
private static $_instance = null;
private function __construct () { }
public static function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new self;
}
return self::$_instance;
}
public static function user( $userId )
{
self::$id = $userId;
return self::$_instance;
}
public static function check()
{
self::$permission = true;
return self::$_instance;
}
public static function item( $item )
{
return $item;
}
}
$bar = Permission::getInstance()->user(100)->item("HELLO");
print_r($bar);
You can chain methods in 'dynamic' classes by returning $this at the end of method (remember, you have a static).
class A {
public function someMethod()
{
// some code
return $this
}
public function otherMethod()
{
// some code
return $this
}
$a = new A();
$a->someMethod()->otherMethod();
}
I have something like this:
class MyParent {
protected static $object;
protected static $db_fields;
public function delete() {
// delete stuff
}
public static function find_by_id($id = 0) {
global $database;
$result_array = self::find_by_sql("SELECT * FROM " . static::$table_name . " WHERE id=" . $database -> escape_value($id) . " LIMIT 1");
return !empty($result_array) ? array_shift($result_array) : false;
}
public static function find_by_sql($sql = "") {
global $database;
// Do Query
$result_set = $database -> query($sql);
// Get Results
$object_array = array();
while ($row = $database -> fetch_array($result_set)) {
$object_array[] = self::instantiate($row);
}
return $object_array;
}
private static function instantiate($record) {
$object = self::$object;
foreach ($record as $attribute => $value) {
if (self::has_attribute($attribute)) {
$object -> $attribute = $value;
}
}
return $object;
}
}
class TheChild extends MyParent {
protected static $db_fields = array('id', 'name');
protected static $table_name = "my_table";
function __construct() {
self::$object = new TheChild;
}
}
$child= TheChild::find_by_id($_GET['id']);
$child->delete();
I get this: Call to undefined method stdClass::delete() referring to the last line above. What step am I missing for proper inheritance?
You never actually instanciate the TheChild class, which should be done by
$var = new TheChild();
except in TheChild constructor itself.
So, the static $object field is never affected (at least in your example), so affecting a field to it (the line $object -> $attribute = $value; ) causes the creation of an stdClass object, as demonstrated in this interactive PHP shell session:
php > class Z { public static $object; }
php > Z::$object->toto = 5;
PHP Warning: Creating default object from empty value in php shell code on line 1
php > var_dump(Z::$object);
object(stdClass)#1 (1) {
["toto"]=>
int(5)
}
This object does not have a delete method.
And as said before, actually creating a TheChild instance will result in an infinite recursion.
What you want to do is this, probably:
class TheChild extends MyParent {
protected static $db_fields = array('id', 'name');
protected static $table_name = "my_table";
function __construct() {
self::$object = $this;
}
}
Edit: Your updated code shows a COMPLETE different Example:
class MyParent {
protected static $object;
public function delete() {
// delete stuff
}
}
class TheChild extends MyParent {
function __construct() {
self::$object = new TheChild;
}
}
$child = new TheChild;
$child->delete();
Calling "Child's" Constructor from within "Child's" Constructor will result in an infinite loop:
function __construct() {
self::$object = new TheChild; // will trigger __construct on the child, which in turn will create a new child, and so on.
}
Maybe - i dont know what you try to achieve - you are looking for:
function __construct() {
self::$object = new MyParent;
}
ALSO note, that the :: Notation is not just a different Version for -> - it is completely different. One is a Static access, the other is a access on an actual object instance!
Through out our application we have something very similar to this:
$cache = App_Cache::getInstance()->newObject(300);
$sig = App_Cache::getCacheName(sha1($sql));
$res = $cache->load($sig);
if ($res === false) {
$res = $db->fetchAll($sql);
$cache->save($res, $sig);
}
The problem at the moment is that we end up creating a new object of Zend_Cache each time and for each request this can end up getting called 300+ times.
class App_Cache {
protected static $_instance = null;
public static $enabled = true;
protected $frontend = null;
protected $backend = null;
protected $lifetime = null;
public function __construct() { }
public static function getInstance() {
if (is_null(self::$_instance))
self::$_instance = new self();
return self::$_instance;
}
public function newObject($lifetime = 0) {
return Zend_Cache::factory('Core','Memcached',$this->getFrontend($lifetime),$this->getBackend());
}
public static function getCacheName($suffix) {
$suffix = str_replace(array("-","'","#",":"), "_",$suffix);
return "x{$suffix}";
}
In Magento they seem to create it once in the __construct, where as Concrete5 create a static property.
My question is whats the best solution?
I think your getInstance() method should be returning your instance of Zend_Cache rather than App_Cache. Try something like this:
class App_Cache
{
protected static $_instance = null;
protected static $_cacheInstance = null;
public static $enabled = true;
protected $frontend = null;
protected $backend = null;
protected $lifetime = null;
public function __construct() { }
public static function getInstance() {
if (is_null(self::$_instance))
self::$_instance = new self();
return self::$_instance;
}
public function newObject($lifetime = 0) {
if (is_null(self::$_cacheInstance))
self::$_cacheInstance = Zend_Cache::factory('Core','Memcached',$this->getFrontend($lifetime),$this->getBackend());
return self::$_cacheInstance;
}
public static function getCacheName($suffix) {
$suffix = str_replace(array("-","'","#",":"), "_",$suffix);
return "x{$suffix}";
}
}
Notice that I changed the newObject() method to be static and added the parameter for it into getInstance(). In this way, you can call getInstance() throughout your code and it will only create the Zend_Cache instance once and then save it in the App_Cache object's $_instance variable.
Ok, changed the code to hold a static instance of the Zend_Cache object and return it if requested. This will only create the instance once. I think the method name should be changed to getCache() or something like that so it's clearer what it is doing.
I want to pass php variable $aa into a class function. I have read some articles
in php.net, but I still don't understand well. Can anyone help me put the variable into this class? thanks.
$aa='some word';
class Action {
private $_objXML;
private $_arrMessages = array();
public function __construct() {
$this->_objXML = simplexml_load_file($aa.'.xml');
}
}
Simply put the variable names in the constructor.
Take a look at the snippet below:
public function __construct( $aa )
{
// some content here
}
I'm not sure what you mean... do you mean you want to access $aa in a function? If so:
$aa='some word';
class Action {
private $_objXML;
private $_arrMessages = array();
public function __construct() {
global $aa;
$this->_objXML = simplexml_load_file($aa.'.xml');
}
}
Or, on a per instance basis, you can do things like:
$aa='some word';
class Action {
private $_objXML;
private $_arrMessages = array();
public function __construct($aa) {
$this->_objXML = simplexml_load_file($aa.'.xml');
}
}
new Action($aa);
$aa='some word';
class Action {
private $_objXML;
private $_arrMessages = array();
public function __construct($aa) {
$this->_objXML = simplexml_load_file($aa.'.xml');
}
}
And use it like this:
$instance = new Action('something');
I don't know php, but my logic and google say this:
class Action {
private $_objXML;
private $_arrMessages = array();
public function __construct($aa) {
$this->_objXML = simplexml_load_file($aa.'.xml');
}
}
$object = new Action('some word');
This is simply called pass a variable as parameter of a function, in this case the function is the constructor of Action