I have a problem with including classes. Here's a simple example to explain the problem:
Class no. 1 (path: /home/day/Class_A.php):
class Class_A {
public function sayHi() {
echo "Good day";
}
}
Class no. 2 (path: /home/test/Class_B.php):
class Class_B {
public function greeting() {
if(class_exists("Class_A")!=true)
include "../day/Class_A.php";
$test = new Class_A();
$test->sayHi();
}
}
PHP file (path: /home/php.php)
if(class_exists("Class_B")!=true)
include "test/Class_B.php";
$g = new Class_B;
$g->greeting();
The problem is when php.php includes Class_B and Class_B includes Class_A, Class_B fails to open Class_B because the path of the object of the class is now the same as the php.php file.
My question is:
Is there a good and simple way to get around this?
Try changing:
include "../day/Class_A.php";
to
include dirname(__FILE__) . '/../day/Class_A.php';
This way, your include will be relative to the file that is doing the include (Class_B).
Looks like greeting is not a static function so you can't do:
Class_B::greeting();
You'd have to get a class B object and called greeting on it or add static to greetings declarations.
Second, why not uuse require_once? In php.php
require_once('test/ClassB.php');
And in ClassB.php:
require_once('../day/ClassA.php');
Use __autoload which is a magic function, that you define, that enables PHP to let you know when it doesn't have a class loaded, but that class needs to be loaded.
If you define the __autoload function like so,
function __autoload ($classname)
{
require('/path/to/my/classes/'.$classname.'.php');
}
you no longer need to add
require_once('/path/to/my/classes/MyClass.php');
into your files, because the first time that PHP encounters
$mine = new MyClass();
or
MyClass::staticMethodCall();
it will automatically call the __autoload function that you defined earlier.
__autoload('MyClass');
Resource: http://blog.samshull.com/2010/02/why-you-should-use-autoload-function-in.html
Related
Inside a method in my Model class, I include another PHP file. The code works until that included PHP file declares a class definition ie class Test123 {}.
The class name is unique. The only possible source of the issue that I could think of would be how I'm including a class within a class. However, I wasn't able to find information about this, so I assume it isn't a problem.
Any ideas?
//Inside of method inside of model class
include "{$_SERVER['DOCUMENT_ROOT']}/models/language.php";
I believe you're right in assuming that you can't declare a class inside a class, which is what you're essentially doing by including it inside a class method.
Could you perhaps do something like this?
class.php:
<?php
include("otherclass.php");
class MyClass {
public function run () {
$otherClass = new OtherClass();
}
}
otherclass.php:
<?php
class OtherClass {
}
index.php:
<?php
include("class.php");
$myClass = new MyClass();
$myClass->run();
I'm trying to autoload Classes, but I'm hindered by the scope. The Class is being loaded, but I'm using it out of scope. Here's the code to further explain what I'm trying to do.
AutoLoader.php
<?php
class AutoLoader {
private $namespace;
public function __construct($namespace) {
$this->namespace = $namespace;
spl_autoload_register(array($this, 'ClassLoader'));
}
private function ClassLoader($class) {
$class = "classes/{$this->namespace}/{$class}.php";
print("Loading class: {$class}");
include "{$class}";
}
}
?>
script.php
<?php
ini_set("display_errors", 1);
$loader = new AutoLoader("myspace");
$MyClassObj = new MyClass();
$result = $MyClassObj->MyClassFun();
?>
So when it comes down to script.php, I get the print out that it's loading the class and I don't get any errors that it can't find the file. So it looks like it's loading, but when I use the class to create a new object, it tells me it can't find the class. So I'm loading the include out of scope.
I included the AutoLoader in a separate file so I could load it into multiple files. Am I able to make this work or must the AutoLoader be part of script.php instead of separate?
edit: Including error, added error display to script.php.
Loading class: classes/myspace/MyClass.php
Fatal error: Class 'MyClass' not found in /usr/local/apache2/htdocs/scripts/script.php on line 5
edit: Including MyClass.php and directory structure
MyClass.php
<?php
class MyClass {
public function MyClassFun() {
$var = "hello world";
return $var;
}
}
?>
Directory Structure
htdocs/scripts/script.php
htdocs/classes/myspace/MyClass.php
htdocs/AutoLoader.php
If I change the class to MyClasse (misspelled) it will error on the include because it can't find the file. So using the proper MyClass I can only assume that it's finding the file since it's not producing an error. So the include looks good, but it still won't use it.
Which, now that I think about it more, is strange. The include is only occuring because of line 5 when I go to use the class. ClassLoader is being called by the spl_auto_register to search for the class. It's finding and including the class. Yet the same line 5 fails to actually use it.
I guess I don't understand that disconnect. Line 5 is properly calling the ClassLoader, but then fails to actually find the class once loaded.
I'm a newbie in php but I'll try to get straight to the point.
I have a class called ConnectionManager
class ConnectionManager
{
function ConnectToDB()
{
//PDO connection code
}
}
and in my other manager InstitutManager I am using require_once($filename) to get access to my ConnectionManager functions
require_once('../manager/ConnectionManager.php');
class InstitutManager
{
protected $connInstance;
function _construct()
{
$this->connInstance = new ConnectionManager;
}
function getInstituts()
{
$conn = $connManager->ConnectToDb();
//retrieve instituts
}
}
The question is : Should I be using extends ConnectionManager in my InstitutManager instead of require_once? Why should I use one more than the other?
Thanks
Edit : Changed code for InstitutManager class
Would this be ok like this? Or should I pass a pass a parameter with my connection already instanciated in function _construct($conn)?
Your include_once reads in a source file, which in this case has a class definition for ConnectionManager in it. Your extends sets up class InstitutManager as inheriting class ConnectionManager, i.e. InstitutManager gets everything in ConnectionManager and can then define its own modifications to that basic structure. There isn't really any relationship at all between the two operations, and your $connManager = new ConnectionManager operations are nonsensical.
require_once 'file'.php' just means that the PHP interpreter will take the contents of a file called file.php and dump it right there in the spot where the include was called. Kind of like what would happen if you would select everything in a Word file, click copy and paste it at the top of another Word file.
In your case you need to include the file, or else it will not know where to find the ConnectionManager class.
I'm coding a Wordpress plugin and I'm not sure regarding the function name conflict..
I have a file named test_handling.php which contains the following content :
function testing() { echo 'test'; }
I included this file in a class constructor (file named testcls.class.php) :
class TestCls {
function __construct() {
require_once('test_handling.php');
testing();
}
function otherfunction() {
testing();
}
// ...
}
In this case, I would like to know if the testing() function is only available in the TestCls class, or can it create conflicts if an other WP plugin has a function with the same name ?
Even with the same name, the functions will have different scope if defined as class method. To make a call to a regular function you will do the following:
testing();
and the result will be:
'test'
the class method need an instance of the class or be statically called. To call the method class you will need the following formats:
$class->test();
or
OtherPlugin::test();
To sum up, the function test will be different if defined as class method. Then, you will not have conflicts.
Other way to encapsulate your function and make sure you are using the right one is with namespaces. If you use a namespace in your test_handling.php
<?php
namespace myname;
function testing(){echo 'test';}
?>
You will access the function test like this:
<?php
require_once "test_handling.php";
use myname;
echo myname\testing();
Now you are sure about the function you are calling.
When a file is included, the code it contains inherits the variable
scope of the line on which the include occurs. Any variables available
at that line in the calling file will be available within the called
file, from that point forward. However, all functions and classes
defined in the included file have the global scope.
from include in PHP manual
Which means that yes, you can have conflicts.
I am stumped right now. In my last post about this question the answer was to use a singleton to make sure an object is only initiated 1 time but I am having the opposite problem.
If I have a file called index.php and then I include these files into it, class1.php, class2.php, class3.php, class4.php.
In index.php I will have,
<?PHP
$session = new Session();
require_once '/includes/class1php';
require_once '/includes/class2.php';
require_once '/includes/class3.php';
require_once '/includes/class4.php';
?>
then in all 4 of the test files I will try to access a method called get() from the session class, assume the session class file is already included into the index.php page as well.
Now if I try to use...
$testvar = $session->get($var1);
in any of the test class files I will get this error
Fatal error: Call to a member function get() on a non-object
the only way the code works without an error is if I use
$session = new Session();
in every file.
How can I fix/avoid having to initaite the class in every file when it is already initated in the index.php file?
the goal is to let me initiate a class in 1 file like index.php and then include the class files into that page, the catch is most of the classes use methods from other classes so would be nice if I didn't have to initiate every class in every file
Without seeing the code it's hard to tell, but I think I can make some assumptions. correct me if I'm wrong:
EDIT: So post your source so we can stop speculating
1) The files you are including are class files. in other words, they contain something like:
class a
{
function a(){}
function b()
{
}
}
2) You aren't trying to execute code in the class files, at load time, but at some later time by instantiating them
i.e.
require("class.a.php");
$myA = new a();
$a->b();
If you are trying to reference your session variable inside those classes, then you have a scope issue. A variable declared outside a class definition can't be used inside the class, unless it is declared as a global var inside the class.
class a
{
function a(){}
function willFail()
{
$session->doSomething(); //fails
}
function b()
{
global $session;
$session->doSomething(); //succeeds
}
}
Even then, you probably don't want to do that, but instead you should pass in your session as a variable if the class needs access to it:
class a
{
function a(){}
function b($session)
{
$session->doSomething(); // yay!
}
}
You could have a base class they all all extend from
Example
class test1 extends Base {
public function doSomething() {
$this->session->get('something');
}
}
class Base {
protected session;
public function __construct() {
$this->session = new Session();
}
}
You're kind of thinking about it backwards. Any file that will use the session object will need to include the file containing that class definition. The alternative is to use __autoload to pull the class in:
function __autoload($classname)
{
if ($classname == 'Session')
{
include_once 'Session.php';
}
}
EDIT : you'll need to put the file containing that autoload into every file that will use it.