PHP Method Disappears? - php

I am including one PHP script into another using PHP's require_once() method. This script contains a class, TemplateAdmin, which instantiates itself right after the script, like this:
class TemplateAdmin {
// Class body...
}
$templateAdmin = new TemplateAdmin();
This was working fine for a while. However, I have adopted a new importing technique to include classes and packages. I have tested this new technique, and it works! However, for some strange reason, none of the methods in any of the classes I import are there when I need them. However, it seems as though the instance variables are still there.
For example, when a class with this absolute path is called:
require_once("C:\wamp\www\wave_audio\system\server\templates\TemplateAdmin.php");
... I get this error in the call stack:
Fatal error: Call to undefined method stdClass::top() in C:\wamp\www\wave_audio\cms\index.php on line 189
This error is referring to my use of the top() method inside of the TemplateAdmin class.
Does any one have any idea as to why this is happening??? If this helps, I have been using require_once() all along, I am running PHP 5.3.5 on a Windows XP Media Center machine.
Thank you for your time!

Assuming you dont want to use globals here is one way that only requires a few changes.
TemplateAdmin.php:
class TemplateAdmin {
// Class body...
}
return new TemplateAdmin();
Return include once in import:
function import($classes) {
//Convert ECMAScript style directory structures to Unix style
$address = str_replace(".", "/", $classes);
$address = INSTALL_ROOT . "system/server/" . $address . ".php";
if (file_exists($address) && is_file($address)) {
return require_once($address);
} else {
die(""" . $classes . "" does not link to an existing class");
}
}
Assign the variable:
$adminTemplate = import('templates.TemplateAdmin');

I have a feeling your php error message is accurate. I know on your stripped down version, you pieced it together how you're sure it's setup but it's obviously not a direct copy/paste since it's like:
class TemplateAdmin {
public function top() {
//The "top" method...
}
}
So, the error message says that the method "top" is not defined. If it were not including your file properly, it would tell you that the class you instantiated doesn't exist. Either that method does not exist in the class you think it is, or the method has been unset somewhere in that object instance. Trust your error message.

Related

PHP class includes a file, but that file cannot access the class

I have a php class that uses "include" to load some html and php from a file. Within that file I want to access the class object that included the file, but I keep getting "Fatal error: Call to a member function makeSizesSelect() on a non-object ..."
I've tried both include and require, I've tried declaring globals, I've tried everything I can think of and everything I've so far found on SO. Nothing seems to allow the file I include to have php code access the object that included it.
Any ideas?
Here's a few snippets ...
The class file:
class cdf {
public $version = 001;
public function cdf_shortcode( $atts,$content )
{
$this->slog( 2,"shortcode() case: show" );
require( 'templates/container.php' );
}
}
And the required file container.php contains the following (amongst other stuff):
<?php
echo "version = ".$this->version;
?>
I then try to use the object:
$cdf = new cdf();
$cdf->cdf_shortcode( null, null);
The line $this->slog( 2,"shortcode() case: show" ) works. It runs that function (which I haven't included in this snippet) just fine. But then the file I require (or include) cannot use $this to access the object. I'm at a loss. :-(
All I want to do is access within the included file, the variables and methods in the class that included the file ...
Sorry, some added information. I'm not sure if this makes any difference. The code above is all part of a WordPress plugin.
Curious issue with a curious solution. I finally found the answer over here:
Possible to access $this from include()'d file in PHP class?
I tried all the obvious solutions this poster tried (globals, casting to another variable, etc) with the same lack of success. Turns out, just changing the file extension from .php to .tmpl fixed the issue, and my included file can now access the object that included it. Weird. (Of course, the downside now is that my IDE doesn't colour my code for me. :-( )
Thanks for your suggestions guys.
In the file you included you need to instantiate the class.
<?php
$yourClass = new cdf();
echo "version = ".$yourClass->version;
?>
When you want to access a function in a class, you need to instantiate the class first otherwise you wont have access to anything inside of it.
Also make sure the file you are including wont be included anywhere else where the class cdf doesn't exist because that will result in an error.
The variable $this can only access methods, variables, etc. only if they are in the same object.
Update based on your answer that seems to have worked:
Example.php
<?php
echo $this->returnString();
echo $this->randomVariable;
File.php
<?php
class IncludedClass
{
public $randomVariable = 123;
public function returnString()
{
return "some random string";
}
public function meh()
{
require_once('Example.php');
}
}
$meh = new IncludedClass();
$meh->meh();

Calling function in PHP class not working

I have a a class stored in path plug/PHPDocumentParser/DocumentParser.php:
namespace LukeMadhanga;
class DocumentParser {
static function parseFromString($string) {
// do stuff
}
}
I want to call the class and function. I run this in a file that's stored at the base folder:
include_once("plug/PHPDocumentParser/DocumentParser.php");
$docObj = new DocumentParser();
$docText = $docObj->parseFromString('hello world');
I receive this error:
Fatal error: Class 'DocumentParser' not found
I am pretty sure the problem is how I call the class, correct?
You are calling static function in wrong way. Try
DocumentParser::parseFromString()
Also use require_once, you will know if it was included correctly. (maybe path is wrong.)
Edit : Ok, you added namespace now - it should be \LukeMadhanga\DocumentParser::parseFromString() thats also why you dont get instance of DocumentParser using new.
Of course you can always add use keyword at top of your file to include your namespace.

The script tried to execute a method or access a property of an incomplete object

I'm getting an error, the full error is:
Fatal error: authnet_cart_process() [<a href='function.authnet-cart-process'>function.authnet-cart-process</a>]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "AuthnetCart" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in /home/golfetc/public_html/wp-content/plugins/sccp-2.4.0/authnet_functions.php on line 1266
I'm using session to store cart object in it and get it later at some point. The authnetCart is basically class for cart object.
// Check cart in session
if(isset($_SESSION['AUTHNET_CART'])) {
// Get cart from session
$authnetCart = $_SESSION['AUTHNET_CART'];
foreach($authnetCart->getCartItems() as $item) { // Line#1266
if ($item->getItemId() == $subscription_details->ID ) {
$addNewItem = false;
break;
}
}
......
You can see at line 1266, the code doesn't allow me to access its method. Any help will be highly appreciated. Thanks
You need to include / require the php with your class BEFORE session_start() like
include PATH_TO_CLASS . 'AuthnetClassFilename.php';
session_start();
if (isset($_SESSION['AUTHNET_CART'])) {
//...
}
It seems like your answer is in the error message.
Before unserializing AUTHNET_CART, include the class which defines it. Either manually, or using an autoloader.
include PATH_TO_CLASS . 'AuthnetClassFilename.php';
if(isset($_SESSION['AUTHNET_CART'])) {//...
It doesn't appear that you're actually unserializing it either (I'm assuming this was serialized before stuffing it into the session?)
if(isset($_SESSION['AUTHNET_CART'])) {
// Get cart from session
/** UNSERIALIZE **/
$authnetCart = unserialize($_SESSION['AUTHNET_CART']);
foreach($authnetCart->getCartItems() as $item) { // Line#1266
if ($item->getItemId() == $subscription_details->ID ) {
$addNewItem = false;
break;
}
}
...
None of the other answers in here actually solved this problem for me.
In this particular case I was using CodeIgniter and adding any of the following lines before the line that caused the error:
$this->load->model('Authnet_Class');
OR
get_instance()->load->model('Authnet_Class')
OR
include APPPATH . '/model/Authnet_Class.php';
Did not solve the problem.
I managed to solve it by invoking the class definition in the construct of the class where I was accessing Authnet_Class. I.e.:
class MY_Current_Context_Class extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->model('Authnet_Class');
}
// somewhere below in another function I access Authnet_Class ...
I now understand that the context where you access the Authnet_Class class, needs to have its definition present on the context's class construct (and not just before you invoke the properties of Authnet_Class).
I do not recommend this technique, but there is a way to get around this error :
if( get_class($myObject)=='__PHP_Incomplete_Class' )
$myObject = unserialize(preg_replace('/^O:\d+:"[^"]++"/', 'O:'.strlen('MyClass').':"MyClass"', serialize($myObject)));
Having a good site architecture is obviously the right solution, but it can help temporarily until the problem is fixed
If you're using an MVC framework with a front controller, you need to have your autoload statement before your session_start statement:
[front controller]
//Do this before session start because session has an object that will not work
// if the class has not been loaded already
require_once('vendor/autoload.php');
//Start a session AFTER autoloading
session_start();

Can spl_autoload be placed in another file?

I'm currently making my first website with PHP. Rather than writing autoload for each individual page, I wish to create one file with a general autoload ability.
Here is my autoloadControl.php:
// nullify any existing autoloads
spl_autoload_register(null,false);
//specify extensions that may be loaded
spl_autoload_extensions('.php. .class.php');
function regularLoader($className){
$file = $className.'.php';
include $file;
}
//register the loader function
spl_autoload_register('regularLoader');
Here is my index.php file:
require("header.php");
require("autoloadControl.php");
$dbConnection = new dbControl();
$row=$dbConnection->getLatestEntry();
Currently, the $dbConnection = new dbControl() gives me the following error:
Fatal error: Class 'dbControl'
So my question is, is there a way to use autoload this way or must I place it at the top of every PHP file I write that uses another file?
Placing spl_autoload in an external file is both valid and a good practice for making your code more maintainable--change in one place what could be 10, 20, or more.
It appears that your dbControl class is not being provided in the code you provided. Assuming you are including the class before referencing it, and the class works properly, then you should have no problem accomplishing this task.
require("header.php");
require("autoloadControl.php");
$dbConnection = new dbControl(); // Where is this class located?
Here is an OOP approach for your autoloadControl.php file:
<?php
class Loader
{
public static function registerAutoload()
{
return spl_autoload_register(array(__CLASS__, 'includeClass'));
}
public static function unregisterAutoload()
{
return spl_autoload_unregister(array(__CLASS__, 'includeClass'));
}
public static function registerExtensions()
{
return spl_autoload_extensions('.php. .class.php');
}
public static function includeClass($class)
{
require(PATH . '/' . strtr($class, '_\\', '//') . '.php');
}
}
?>
Your problem is not related to where you are defining your callback, but how.
Using spl_autoload_extensions('.php') would achieve the same thing as your custom callback; you don't need both if your callback is as simple as this. Your comment is also wrong - calling spl_autoload_register with no arguments will not clear current callbacks, but it will register the default callback.
However, in your code, you have specified the argument to spl_autoload_extensions incorrectly - it should be a comma-separated list of extensions. So I think what you want is this:
// Tell default autoloader to look for class_name.php and class_name.class.php
spl_autoload_extensions('.php,.class.php')
// Register default autoloader
spl_autoload_register();
// READY!
The main difference this will make from your code is that the default autoloader will look for 'dbcontrol.php' (all lower-case) whereas yours will look for 'dbControl.php' (case as mentioned in PHP code). Either way, you certainly don't need both.

confusing "cannot redeclare class" error (PHP)

I have a strange issue. I have a static method that loads classes (load_library). When it loads a particular class, it gives me a "cannot redeclare class" fatal error, but when testing whether the class exists right before using the load_library method to load it, it says the class does not exist. The load_library method works elsewhere without such errors.
If I take the load_library call out, it says it cannot find the class when the class is actually used a few lines later. Stranger still, if I take out my registered class autoload function instead, everything works perfectly, even though this autoload function doesn't even check the directory that the class I'm trying to load is in.
It's a complicated problem involving many files so it is hard to post code, but does this problem smell familiar to anyone out there?
My load_library method:
public static function load_library($name) {
if (!class_exists($name)) {
if (file_exists('application/libraries/' . $name . '.php')) {
include('application/libraries/' . $name . '.php');
} else {
trigger_error('Request made for non-existant library ('.$name.').', E_USER_ERROR);
}
}
}
My call to the load_library method:
lev::load_library('lev_unit_tester/lev_base_test');
My registered autoload method:
public static function autoloader($name) {
if (class_exists($name)) return;
if (file_exists('application/libraries/' . $name . '.php')) {
include('application/libraries/' . $name . '.php');
}
}
The class I am trying to load (this is where the error occurs):
abstract class lev_base_test {
}
The actual error message:
Fatal error: Cannot redeclare class lev_base_test in /some/path/application/libraries/lev_unit_tester/lev_base_test.php on line 5
try this
// Check to see whether the include declared the class
if (!class_exists($class, false)){..}
Your are calling your load_library method this way :
lev::load_library('lev_unit_tester/lev_base_test');
Which means you are testing, with class_exists(), if there is a class called lev_unit_tester/lev_base_test -- which is probably not quite the case : that's not a valid name for a class.
So class_exists() returns false ; and, so, you try to include the file that contains your class every time the load_library method is called.
There is no problem when you are using autoloading, because PHP will only call your autoloader when it you try to use a class which has not been defined : once the file that correspond to a class has been included, the autoloaded will not be called for that class again.

Categories