I am trying to initiate a class on demand.
class MyClass{
private $modules = array("mod1" => false);
public function __get($name){
if(array_key_exists($name, $this->modules) && !$this->modules[$name]){
$class = ucfirst($name);
$this->$name = new $class();
$this->modules[$name] = true;
}
}
}
I then have another class, which then extends the above class. If I do the following the class doesn't get initiated, and I get an error Fatal error: Call to a member function get() on a non-object
class Home extends MyClass{
public function main(){
echo $this->mod1->get("cat");
}
}
But if I do this, the class does get initiated.
class Home extends MyClass{
public function main(){
$this->mod1;
echo $this->mod1->get("cat");
}
}
Is there any way for me to initiate the class without having to add that extra line?
Just return it after it's instantiated:
class MyClass{
private $modules = array("mod1" => false);
public function __get($name){
if(array_key_exists($name, $this->modules) && !$this->modules[$name]){
$class = ucfirst($name);
$this->$name = new $class();
$this->modules[$name] = true;
return $this->$name;
}
}
}
Now you can do what you want:
class Home extends MyClass{
public function main(){
echo $this->mod1->get("cat");
}
}
Related
I have this class:
class Search
{
protected static $Basics;
public function __construct() {
self::$Basics = new Basics();
}
public static function getT() {
return self::$Basics->get('keywords/t');
}
public static function isAvailable($keyword) {
return self::$Basics->get('keywords/available', ['keyword' => $keyword])['available'];
}
}
The class Basics is really simple class:
class Basics
{
public function __construct()
{
//some code..
}
public function get($keyword, $param = null)
{
return ['available' => true];
}
}
Call to getT function:
use App\Libraries\Search;
class GV
{
public function test() {
echo Search::getT() ? 'ok' : 'bad';
}
}
But, when i run the function getT in class Search, it return this error: Call to a member function get() on a non-object
What can i do?
You are calling the method inside Search statically (Search::getT();) which will never fire the __construct() method.
__construct() gets fired upon instantiating the class ($search = new Search;), not upon calling static methods (Class::method();).
Simply instantiate your search object: $search = new Search;
Like so:
use App\Libraries\Search;
class GV
{
public function test() {
$search = new Search;
echo $search::getT() ? 'ok' : 'bad';
}
}
Im testing this thing where i'm trying to load a class and use it like this:
$this->model->model_name->model_method();
This is what I've got:
<?php
error_reporting(E_ALL);
class Loader {
public function model($model)
{
require_once("models/" . $model . ".php");
return $this->model->$model = new $model;
}
}
class A {
public $load;
public $model;
public $text;
public function __construct()
{
$this->load = new Loader();
$this->load->model('Test');
$this->text = $this->model->Test->test_model();
}
public function get_text()
{
return $this->text;
}
}
$text = new A();
echo $text->get_text();
?>
Im getting a bunch of errors here:
Warning: Creating default object from empty value in
C:\xampp\htdocs\fw\A.class.php on line 9
Notice: Trying to get property of non-object in
C:\xampp\htdocs\fw\A.class.php on line 24
Fatal error: Call to a member function test_model() on a non-object in
C:\xampp\htdocs\fw\A.class.php on line 24
What am I doing wrong? Thanks for any tip!
P.S. not much in the loaded file:
<?php
class Test {
public function test_model()
{
return 'testmodel';
}
}
?>
In the A class' constructor you are not assigning the "loaded" model to anything and later you are trying to use the $model property which has nothing assigned to it.
Try this:
class A {
public $load;
public $model;
public $text;
public function __construct()
{
$this->load = new Loader();
$this->model = $this->load->model('Test');
$this->text = $this->model->test_model();
}
(...)
Problem may be that you have not defined Loader.model as object but treating it like it is.
class Loader {
public $model = new stdClass();
public function model($model)
{
require_once("models/" . $model . ".php");
return $this->model->$model = new $model();
}
}
When you have your class like this you can use
$this->model->model_name->model_method();
Try the following code(UPDATED) if you want to avoid $this->model = $this->load->model('Test') in the constructor.
You can simply load the models by calling $this->loadModel(MODEL) function
<?php
error_reporting(E_ALL);
class Loader {
private $models = null;
public function model($model)
{
require_once("models/" . $model . ".php");
if(is_null($this->models)){
$this->models = new stdClass();
}
$this->models->$model = new $model();
return $this->models;
}
}
class A{
public $load;
public $model;
public $text;
public function __construct()
{
$this->load = new Loader();
$this->loadModel('Test');
$this->loadModel('Test2');
$this->text = $this->model->Test2->test_model();
}
public function get_text()
{
return $this->text;
}
private function loadModel($class){
$this->model = $this->load->model($class);
}
}
$text = new A();
echo $text->get_text();
?>
I have this code and i´m trying to use a object
<?php
class Controller {
public $_view;
public function __construct() {
$this->_view = new View();
return $this->_view;
}
}
class View {
public $_params = array ();
public function set_params($index_name,$valores) {
$this->_params[$index_name] = $valores;
}
public function get_param($index_name){
return $this->_params[$index_name];
}
}
?>
i would like to do this:
class Index extends Controller {
public function index() {
$model = Model::get_estancia();
$usuarios = $model->query("SELECT * FROM usuarios");
$this->_view->set_params(); // cant be used.
$this->load_view("index/index");
}
}
i would like to use the set_parms function.
but i can't see the View Function, then i can not use.
Can someone explain and advise me a good and safe way?
Correction from Phil: If a __construct() method isn't found, PHP will revert to legacy constructor syntax and check for a method with the same name as the object. In your case the method index() is being treated as the constructor, and is preventing the parent's constructor from loading the view object into the $_view property.
You can force a class to inherit a parent's constructor by defining __construct() in the child and calling the parent's constructor:
public function __construct() {
parent::_construct();
}
Here is the fixed code:
<?php
class Controller {
public $_view;
public function __construct() {
$this->_view = new View();
return $this->_view;
}
}
.
class View {
public $_params = array ();
public function set_params($index_name,$valores) {
$this->_params[$index_name] = $valores;
}
public function get_param($index_name){
return $this->_params[$index_name];
}
}
.
class Index extends Controller {
public function __construct() {
parent::__construct();
}
public function index() {
$model = Model::get_estancia();
$usuarios = $model->query("SELECT * FROM usuarios");
$this->_view->set_params(); // cant be used.
$this->load_view("index/index");
}
}
I have this Base class:
class Base
{
public $extA;
public $extB;
function __construct()
{
}
public function Init()
{
$this->extA = new ExtA();
$this->extB = new ExtB( $this );
}
public function Test()
{
return 'Base Test Here!';
}
}
class ExtA extending the Base Class
class ExtA extends Base
{
public function Test()
{
return 'ExtA Test Here!';
}
}
class ExtB extending the Base Class too
class ExtB extends Base
{
private $base;
public function __construct( $base )
{
$this->base = $base;
}
public function Test()
{
return 'ExtB calling ExtA->Test()::' . $this->base->extA->Test();
}
}
$base = new Base();
$base->Init();
var_dump( $base->Test() );
var_dump( $base->extA->Test() );
var_dump( $base->extB->Test() );
I try to call the ExtA class Test() function from the ExtB,
both of ExtA and ExtB is exnteding the Base class.
My question is : is this ok, or have a better, faster solution for this?
The extends is necessary too?
Or simply enough like this
class ExtA
{
...
}
class ExtB
{
...
}
Thanks!
This is weird way of OOP.
The Base class should not know anything about its children so we shall go more correct way. Let's implement Decorator pattern:
interface IExt
{
public function test();
}
abstract class ExtDecorator implements IExt
{
protected $instance;
public function __construct(IExt $ext)
{
$this->instance = $ext;
}
}
class ExtA extends ExtDecorator
{
public function test()
{
return 'ExtA::test here and calling... ' . $this->instance->test();
}
}
class ExtB extends ExtDecorator
{
public function test()
{
return 'ExtB::test is here and calling... ' . $this->instance->test();
}
}
class Base implements IExt
{
public function test()
{
return 'Base::test here!';
}
}
class Printer
{
public static function doMagic(IExt $ext)
{
echo $ext->test()."\n";
}
}
Printer::doMagic($base = new Base);
// Base::test here!
Printer::doMagic($extA = new ExtA($base));
// ExtA::test here and calling... Base::test here!
Printer::doMagic(new ExtB($extA));
// ExtB::test is here and calling... ExtA::test here and calling... Base::test here!
You can play further any way you want
<?php
class FirstClass{
public static $second;
public static $result = 'not this =/';
public function __construct(){
$this->result = 'ok';
$this->second = new SecondClass();
}
public function show(){
echo $this->second->value;
}
}
class SecondClass extends FirstClass{
public $value;
public function __construct(){
$this->value = parent::$result; //Make it get "ok" here
}
}
$temp = new FirstClass();
$temp->show(); //It will show: "not this =/"
?>
How can I make it to print "ok"?
I mean, the SecondClass should know what FirstClass set as result, see?
Replace $this->result = 'ok'; with self::$result = 'ok'; in FirstClass constructor.
Btw, the code is terrible. You're mixing static and instance variables, and extend classes but don't use benefits extension provides.
you need to reference the static as self::$result in the first class.
Below should do what you want...
<?php
class FirstClass{
public static $second;
public static $result = 'not this =/';
public function __construct(){
self::$result = 'ok';
$this->second = new SecondClass();
}
public function show(){
echo $this->second->value;
}
}
class SecondClass extends FirstClass{
public $value;
public function __construct(){
$this->value = parent::$result; //Make it get "ok" here
}
}
$temp = new FirstClass();
$temp->show(); //It will show: "not this =/"
?>