So I have a config.php file, wich is included on top of every page on the site before the tag. This file uses __autoload() to get all the php classes I use. Then, after autoloading them I assign the classes to variables like so...
$myclass = new Myclass();
$mysecondclass = new MySecondClass();
When I want to call $mysecondclass in $myclass, I get an undefined variable error. This is of course, because $mysecondclass was not defined before $myclass. How do I fix this where I can define all classes from any other class?
Thanks for any help:)
The best OOP approach would be to use a superObject with properties which are objects of other classes.
class Context{
var $myClass;
var $myOtherClass;
var $db;
//...
}
In your MyClass
class MyClass{
var $context;
public function __construct(&context){
$this->context = $context;
}
public function otherFunction(){
$this->context->myOtherClass->functionFromOtherClass();
}
}
You should be instantiating these classes using Factory method or any mechanism to manage objects.
To initialize MyClass you would implement something like this.
ObjectFactory::createObject('MyClass',$context);
$myclass is not Myclass it is an instance of Myclass (an object). Objects are not classes. If you want to use a new instance of MySecondClass inside of an instance of Myclass, just instantiate it in there.
Your question also deals with scope. You have created these two objects in the global scope. They are not automatically accessible within one another. If you have some object which you will have only one instance of and which you want to be global and accessible by others, you can import it into their scope with the global keyword. However, this is not usually the best way to go about it. Instead, you may want to look up the Singleton Pattern. It gives you a way to ensure that a particular class is only instantiated one time and gives you a way to access the object that has been created as a result of that instantiation.
The registry pattern is also an easy way to access "global" object anywhere in your code.
You can Take a look at Zend_Registry : http://framework.zend.com/manual/en/zend.registry.using.html
$myclass = new Myclass();
$mysecondclass = new MySecondClass();
Zend_Registry::set('mysecondclass', $mysecondclass);
$myclass->doSomething();
class Myclass
{
public function doSomething()
{
// use $mysecondclass via the registry
Zend_Registry::get('mysecondclass')->methodFromSecondClass();
}
}
class MySecondClass
{
public function methodFromSecondClass()
{
return true;
}
}
According to how your classes works, think about extending them... Extending MyClass to MySecondClass automatically gives access to parent properties / functions.
MyClass
class MyClass{
function myFunction(){
// code here
}
}
MySecondClass
class MySecondClass extends MyClass{
function __construct(){
$this->myFunction();
}
}
Related
I don't understand a concept of class in php. I could be wrong.
I looked at a WordPress plugin. The class was defined and the properties of class wasn't created only functions were created.
Consider this example
class a
{
public function show(){
echo "hello";
$this->something = "xyz" ;
// What is this? How can "something" can be used here;
// as it is not defined in the class?
}
}
Then an object of that class was created in another file.
$obj = new a();
$obj->anothersomething = "abc"; // is it possible?
Enlighten me please.
My question is: Can we assign a value to undeclared property of a class?
Default class visibility is public.
However, it is good practice to explicitly declare class method with it's visibility.
class Foo
{
public function a() {}
protected function b() {}
private function c() {}
}
As #SougataBose mentioned, I'd suggest you running through PHP OOP course
Edit:
When it comes to properties - yes. It is possible to create them dynamically. Again, as a good practice, it is recommended to declare all properties in class body.
In this case it's not a function, but a public class method. Normally you need to define it with public/protected/private keyword, but when skipped, it's just public by default. So then in another file you create an instance of this class and call the public method show() which can then use class instance properties direct. Or you can assign these properties from outside using $obj->anothersomething = "xxx", which is not a good practice. All the assignments should be done through setter methods like this $obj->setProperty($value);
I'm building a PHP OOP MVC Framework for personal use.
I'd like to know if there's a way or the correct implementation of the following:
Being able to call a method from a "subclass" (not extended) to another "subclass". I mean...
I have a class that creates new objects for each subclass instead of using inheritance. Let's call it MainClass, and it has 3 "SubClasses" like this
class MainClass {
public $db;
public $forms;
public $pagination;
function __construct() {
$this->db = new class_db();
$this->forms = new class_forms();
$this->utils = new class_utils();
}
}
And the initialization which is
$MainClass = new MainClass();
I can do for example
$MainClass->utils->show_text("Hello World");
And works fine.
What I'd like to do is... within the $MainClass->utils->test() (Another test method), is to be able to access $MainClass->db without using global or $GLOBALS.
Is there any alternative way of achieving this? To be able to access $MainClass methods and submethods within another submethod (access db from utils and from the main page where MainClass is initialized)? How would it be? I want to be able to access al the submethods, like utils being able to access db and forms method. as well as the pages that are outside MainClass.
Thank you
If utils has to use db, you either have to pass the MainClass instance to utils, so it can call $this->myRefToMain->db, or pass the instance of db itself, so utils can call $this->db. Either way, it cannot (reasonably) crawl up the call stack to find the object that called it.
Object if your class class_utils can exists without MainClass. And its method test() should access some object db of class class_db. This means class_utils depends on class_db and you should inject object of class_db in constructor, for example:
class MainClass {
public $db;
public $forms;
public $pagination;
function __construct() {
$this->db = new class_db();
$this->forms = new class_forms();
$this->utils = new class_utils($this->db);
}
}
I'm changing my class structure around to store common database methods in one class. Then extending it from a child class. This should cut down on code but also allows me to overwrite the parent methods when I need to.
I've done the following, for this example I've simplified to the basics compared to the original code which contains more classes.
class parent_object{
private $table_name;
public function all_records(){
$sql = "SELECT * FROM ".$this->table_name;
return $this->execute_sql($sql);
}
}
class child_object extends parent_object{
protected static $table_name="tbl_name";
public function __construct(){
parent::__construct(self::$table_name);
}
}
I want to call the all_records() statically to save myself creating a new object every time.
I'm stuck having to instantiate the child and then call the parent method
$child = new child_object();
$all = $child->all_records();
What I really want to be able to call the parent method statically:
$all = child_object::all_records();
I understand why I can't do it with my code, but would like some way that the child instantiates first then accesses the parent method.
I could write all_records() method in the child_object to instantiate itself and call the parent all_records() but that sort defeats the purpose of extending to cut down on code and the same methods in my child class.
I'm sure its quite simple or some new high level oop function can do it.
Thanks for your help.
The answer is relatively simple, you can turn all your properties into static properties, and then use static:: instead of self::.
http://php.net/manual/en/language.oop5.late-static-bindings.php
Solving your problem this way is considered a bad practice though. Good luck.
You could do something like this:
class child_object extends parent_object
{
protected static $table_name="tbl_name";
public static function factory()
{
return new child_object();
}
public function __construct()
{
parent::__construct(self::$table_name);
}
}
Then when you use it you just do:
$all = child_object::factory()->all_records();
What I would like to do is chain a few classes together using "extends". It kinda works, but not like I expected it to. So I must be doing something wrong.
From what I gathered, when you extend a class you inherit all of its properties. So with that in mind I like to make my config file available in all classes. To do this I want to extend all classes on an autoLoader class. This seems logical to me, but correct me if I'm wrong.
I have two classes
AutoLoader
Class AutoLoader {
public $oConf = null;
public function __construct($oConfig) {
$this->$oConf = $oConfig;
}
public function getConf() {
return $this->$oConf;
}
}
other class
Class foo extends AutoLoader {
public function bar() {
var_dump($this->getConf());
}
}
My question is, why is the var_dump NULL.
It is strange to me cause this always returns the conf:
$autoLoader = new AutoLoader($array);
var_dump($autoLoader->getConf());
What am I missing here.
You are extending and inheriting the class structure, not the object instance.
Just take this code as an example:
$foo = new Foo('foo');
$bar = new Foo;
Would you expect $bar to have access to the argument 'foo' passed into the first object somehow? No. Extension doesn't change that.
You should be using composition or dependency injection (e.g. pass an autoloader into the constructor of Foo). Don't make Foo an Autoloader, give it an Autoloader if it needs one. When you extend a class, that new class is also its parent class. That means it could be used in place of the parent class. Anywhere you'd use an Autoloader class, you could substitute Foo instead. Does that make sense? Is Foo an Autoloader? Does $foo instanceof Autoloader == true make any sense? No.
If inheriting class have an own constructor, you are probably not passing the oConfig to the parenting class (Autoloader) in the case.
also, your constructor expects an config.
So you should be doing this in your child constructor if you don't have one:
function __construct($oConfig) {
parent::__construct($oConfig);
// rest of your constructor code here
}
You should create instance of foo class and give into constructor your config variable:
$config = 'My_config';
$foo = new foo($config);
$foo->bar();
Will output:
(string) "My_config"
I've been programming in PHP for several years and I've only just recently begun to look at object oriented code. Now I understand classes and such:
class Myclass {
public function __construct() {
}
}
and all that good stuff... I also understand creating functions and calling in my index.php:
$someVar = new Myclass;
One thing I've been trying to understand, being that i've recently looked at codeigniter and I like one thing about it and want to try and accomplish the same thing without actually using codeigniter.
in code igniter they have the variable $this appear to be their class variable. But by using that, you're able to call from multiple classes all at once.. such as:
$this->load->module(); which is in one class file..
$this->db->query(); which is in another class file.
I've searched google for the last few days trying to figure out how to do this same thing where each class would have the correlation between them all allowing me to run $this->class_name->function_name in my projects instead of creating a new variable for each class or for the sake of a clean index file, having every function in a single class file.
Any information (aside from buy this book - as that isn't an option for me) is greatly appreciated and I will thank you now (and will probably thank you again later just for good measure).
I've been reading you and Phil's comments. First off, you can't use $this on index.php. $this can only be used in the context of an object. So you could do,
$someVar = new Myclass;
...
$someVar->db->something();
...instead.
I'm not entirely sure what you mean by "read classes," but you can assign members to MyClass exactly as Phil indicates:
class MyClass {
private $inj;
function __construct(Injected $inj) {
$this->injected = $inj;
}
}
Note that the private $inj declaration is not mandatory, but skipping it is dangerous. Any non-declared members added are automatically public, and this can potentially screw with you if you rely on magical get. I would declare the properties you need.
Finally, you either need to include all class definitions you will use, use a function like load_class(), or use autoloading. If Injected above is not a declared class, you will get an error when trying to create one. load_class() almost certainly includes the class definition somehow.
The load and db references are class properties which are themselves other objects with public module() and query() methods respectively. For example
class MyClass
{
/**
* #var CI_DB
*/
private $db;
/**
* #var Loader
*/
private $load;
public function __construct(CI_DB $db, Loader $load)
{
$this->db = $db;
$this->load = $load;
// PHP also allows you to add arbitrary object properties
// that receive a "public" visibility
// Please note, this is not a good practice
$this->foo = new Foo;
}
public function someMethod()
{
$this->load->module();
$this->db->query();
// You can also use foo even though it is not defined
// in the class properties
$this->foo->something();
}
}
See http://www.php.net/manual/en/language.oop5.properties.php
Adding the foo property like we did is dangerous. Because it receives the public visibility, it may be altered externally to the class.
$class = new MyClass($db, $load);
$class->foo = new Bar;
$class->someMethod(); // will break if Bar does not contain a something() method