Where do I put includes to get the close to properly register? I have tried including both command base and close in ATE, and I've tried including just command base in ATE, with close in command base... no matter what I do, it says Close not found.
class.CommandBase.php
<?php
abstract class CommandBase {
// variables
// abstract functions
// protected function
}
?>
class.Close.php
<?php
class Close extends CommandBase
{
// variables
// functions
// public function __construct
}
?>
class.ATE.php
<?php
class ATE {
// instance variables
// public properties
public function start(){
$command = new Close(); // class 'Close' not found
}
// public function __construct
}
?>
I have tried including both command base and close in ATE
This should work, provided 'command base' is include before 'close'.
include ('class.CommandBase.php');
include ('class.Close.php');
and I've tried including just command base in ATE, with close in
command base
'close' in 'command base' won't work, since 'close' extends 'command base'.
Ideally, I would avoid including class files in other class files, and confine my include statements to whatever script is using the classes.
Class Close needs to include Class CommandBase. Class ATE needs to include Close
class.Close.php
include 'class.CommandBase.php';
class.ATE.php
include 'class.Close.php';
Be aware that this will work as is IF all the files are in the same directory. If they are NOT in the same directory you will need to update this to point to the right location.
You also should look at PHP's method for autoloading classes. BIG help!
http://php.net/manual/en/language.oop5.autoload.php
Related
I have a file with a single include like this one:
file.php
include(dirname(__FILE__)."/anotherfile.php");
class file {
function myfunction() {
$class = new anotherfile();
$class->functionfromanotherfile();
}
function myfunctionToBeTested() {
// do things here
}
}
I'm using travis-ci to run my tests with phpunit, and the problem is that I dont commit the "anotherfile.php" (have the logic and credentials to connect to the database), which makes it not work when I try to include this file in my test script.
tests.php
class tests extends PHPUnit_Framework_TestCase {
public function test_function() {
include(dirname(__FILE__)."/file.php");
$class = new file();
}
}
I could make another file with only the function I need to test and go with it but maybe you guys can come up with other awnser.
Use some kind of dependency injection:
Modify the class you want to test so that it accepts the credentials as parameters of the constructor.
In the test, create fake -or real- credentials and pass them to the constructor of your class.
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 trying to write a class in PHP that acts as a wrapper for a collection of command line tools to make them easier to use from PHP.
I have a single class (MyClass) in a file myclass.php.
I have code that checks to see if the required tools are installed and then sets a constant (TOOLS_AVAILABLE) to either true or false. Although it's not a lot of code, I only want it to run the first time somebody tries to instantiate my class or use any of its static functions. What's the best practice for handling this?
I only want it to run the first time somebody tries to instantiate my class or use any of its static functions.
Well, the best answer is not to have any static methods. Then you can stick the code in a constructor method as per the answer by #treegarden.
If you must have static methods, then you'll need a static flag within the class to indicate when you've called the 'run once' code, so you can avoid running it again. And then call it explicitly from each of your static methods and the constructor. Something like this:
<?php
class myClass {
private static $hasRunOnce = false;
private static runMeOnce()
{
if (!self::$hasRunOnce) {
self::$hasRunOnce = true;
//put your 'run once' code here...
}
}
public static oneOfYourStaticMethods()
{
self::runMeOnce();
//put your static method code here...
//this would be the same for each of your static methods and your constructor.
}
}
Hope that helps.
You need to create a __construct function in your class and put whatever code you want to execute on instantiation in there:
class MyClass {
function __construct(/* arguments */) {
/* your code here */
}
}
The code will get executed only once when someone instantiates the class.
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.
This is a tricky one.
I am "emulating" ZF Bootstrapping (surface appearance). Don't ask me why, call it academic interest. So I have a Bootstrap Abstract with a method "run" that iterates over itself to locate any methods prefixed with "init".
The application looks for a user defined class which extends this class, in which the user can define any number of methods in this way. However, I want to prevent the user from being able to execute the "run" command of it's parent class, while still exposing the same command for the client code.
class Bootstrap_Abstract{
protected final function run(){
// if method exists that starts 'init' - execute the method
}
}
class Bootstrap extends Bootstrap_Abstract(){
public function initSomething(){
//do something
}
//PREVENT THIS
public function initRun(){
$this->run();
}
}
//application code, not exposed to user - changes in behaviour require changes in this code directly
class Application(){
$Bootstrap = new Bootstrap();//load user bootstrap
$Bootstrap->run();
}
To determine "what" called a particular method, look into debug_backtrace
Post Script:
the problem with my original code was an error in design. The responsibility for iterating through the Bootstrap methods should have been given to the invoking class, not the target class itself.
I solved this problem by moving the function out to the invoker. Funny how obvious/simple refactoring is in hindsight...