PHP 'non-object' error [duplicate] - php

This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I'm working on a small MVC framework in PHP for an exercise. PHP, however, doesn't seem to like my Controller class. The class contains an instance of a loader that loads views:
abstract class Controller
{
public $load;
function __construct($load)
{
$this->load = $load;
}
abstract public function index();
}
From there, I can override Controller for all my controllers. For instace, my index controller:
class Index extends Controller
{
public function index()
{
$this->load->view("hello_world");
}
}
But when I create it:
require 'Controller.php';
require 'Load.php'
require 'controllers/Index.php';
$i = new Index(new Load());
$i->index();
I get this error:
PHP Fatal error: Call to a member function view() on a non-object in /var/www/controllers/Index.php on line 7
Can you guys help me out? I know I set the load in the constructor, and the load class does have a method called view, so why is it giving me this error?
Also: Load class, just for good measure
class Load
{
public function view($filename, $data = null)
{
if(is_array($data)) extract($data);
include ROOT.DS.'views'.DS.$filename.'.php';
}
}

The problem is with this code, and it's not always obvious:
class Index extends Controller
^^^^^
{
public function index()
^^^^^
{
$this->load->view("hello_world");
}
}
This is the same name and therefore a PHP 4 backwards compatible constructor. The parent's constructor then is not called, $load not set and the function not defined.
Knowing this, there are many solutions, including:
namespace DelishusCake;
Introduce a Namespace
This automatically fixes your issue. You need to place this on top of the file.
class Index extends Controller
{
public function index($load = NULL)
{
isset($load) && $this->load = $load;
$this->load->view("hello_world");
}
}
Make the PHP4 backwards compatible constructor work
Or:
class MyIndex extends Controller
{
public function index()
{
$this->load->view("hello_world");
}
}
Rename the class
Or:
class Index extends Controller
{
public function __construct($load) {
parent::__construct($load);
}
public function index()
{
$this->load->view("hello_world");
}
}
Add a PHP 5 constructor, call the parent's constructor
Keep in mind that you only need this because it's the same name. The in depth description you can find as well in the PHP Manual on the Constructors and Destructors page.

You need to instantiate the parent class.
class Index extends Controller
{
public function __construct($load) {
parent::__construct($load);
}
public function index() {
$this->load->view("hello_world");
}
}

Related

codeigniter libraries dependancies

Im trying to pass objects between classes in code igniter and am currently failing. What am I doing wrong. Let me strt showing the pure.php version
Errors.php
<?php
class Errors
{
public function __construct(){}
public function setError($msg){}
}
OtherClass.php
<?php
class OtherClass
{
public function __construct(Errors $errorObject) {}
public function someMethod() {}
}
Then in my main controller..
Controller.php
<?php
class Main
{
public function __construct()
{
$this->errors = new Errors;
$this->other = new OtherClass($this->errors);
}
}
By doing this. I can add errors as I go to my error Object, across any objects i instantiate from the Main controller.
Now my code igniter version looks like this
/library/Errors.php
<?php
class Errors
{
public function __construct(){}
public function setError($msg){}
}
/library/OtherClass.php
<?php
class OtherClass
{
public function __construct(Errors $errorObject) {}
public function someMethod() {}
}
Then in my main controller..
Controller.php
<?php
class Main extends CI_Controller
{
public function __construct()
{
$this->load->library('Errors');
$this->load->library('OtherClass',$this->errors);
}
}
When I do this I get an error in my OtherClass saying that $errorObject is not an instance of Errors. Why is the object not being passed?
The problem is with $this->load->library which is defined like this.
public function library($library, $params = NULL, $object_name = NULL)
$params is expected to be an array. If it is not then the $params is set to NULL.
To get around this requires a bunch of monkey biz.
class Errors is unchanged but class OtherClass needs to be changed to...
class OtherClass
{
public function __construct($errorObject)
{
var_dump($errorObject[0]); //so we can prove it got passed
}
public function someMethod(){}
}
Note the removal of the type hint Error from the constructor declaration. Also, we access index 0 of the argument. The reason lies in what happens at the controller.
function __construct()
{
parent::__construct();
$this->load->library('Errors');
$this->load->library('OtherClass', [$this->errors]);
}
We have to put $this->error in an array so that load->library() won't mess with it.
The alternative is to not use "The CodeIgniter Way" and use good old fashion `new' instead. The controller then is...
function __construct()
{
parent::__construct();
$this->load->library('Errors');
$this->other = new OtherClass($this->errors);
}
And other class reverts to...
class OtherClass
{
public function __construct(Errors $errorObject)
{
var_dump($errorObject);
}
public function someMethod(){}
}
Now the problem is that without adding an autoloader to the system you wind up with
Fatal error: Class 'OtherClass' not found in ...
This LINK goes to a page that talks about the various ways to add an autoloader to CI. I know this has been answered on SO too. But I'm failing to find it at the moment.

Cannot set Parent property from child class

I have view class like this:
class View {
public function __construct() {
}
public static function render($name) {
require 'views/user/header.php';
require 'views/user/'.$name.'.php';
require 'views/user/footer.php';
}
}
and I call the view class in controller like this:
class Controller {
function __construct() {
$this->view = new View();
}
}
and then I set the view property from controller child class, like this:
class Index extends Controller {
function __construct() {
parent::__construct();
$this->view->js = "test";
}
public function index() {
$this->view->render('index/index');
}
}
But when I want to get $this->js from "header.php" which is set at render function on view class, I always get this error message:
Fatal error: Uncaught Error: Using $this when not in object context
I was tried to check, Am I in the right class? using this methods in "header.php" file:
echo get_class(); // and this method return "View";
that means I was on the view class, right?
Can anyone please help me?
Thanks in advance
You have defined render() as a static method, but you are calling it as it was not static.
I would probably benefit from reading this: http://chadminick.com/articles/simple-php-template-engine.html
P.S. What you call "view" is just a template.

Declare 2 class with same name but can't use namespace issue

I created my own autoload for my cms. But when my project is getting bigger than i thought. I used namespace. but i realize that i can't use use inside my autoload function.
Is there anyway to load 2 class with same name but different namespace.
I have 2 class:
HumanDao.php:
class HumanDao extend Dao{
public function __construct(){
parent::__construct();
}
public function doSomething(){
.....
}
}
Monster.php
class MonsterDao extend Dao{
public function __construct(){
parent::__construct();
}
public function doSomething(){
.....
}
}
Dao.php
class Dao {
public function __construct(){
loadAdapter();
}
private function loadAdapter($folder,$name){
//load all adapters of a dao with their own model
}
public function doSomething(){
.....
}
}
But my project's getting bigger than i thought.
I have 2 adapter with same name BodyAdapter but different in code, and loaded by different DAO and work with 2 different model,different folder. At first, i thought it's ok. Because each of DAOs only loads a BodyAdapter. But Php still throw out Can't redeclare. So i added namespace into each Adapter(namespace: Human,Monster). and try:
public function loadAdapter($folder,$name){
use $folder;
include $folder.$name;
$this->name = $name::getInstance();
}
But php can't parse use keyword in a function.
So i'm stuck at here.
Could someone give me help me?

Why can't i use __construct methods in controllers in OpenCart with vqmod [duplicate]

This question already has answers here:
Reference - What does this error mean in PHP?
(38 answers)
Closed 3 months ago.
I have tried adding just an empty __construct method to a module controller.
Fatal error: Call to a member function get() on a non-object in /var/www/rodebutik.dk/public_html/wb/vqmod/vqcache/vq2-system_engine_controller.php on line 16
Line 16:
public function __get($key) {
return $this->registry->get($key);
}
The most likely explanation: the original constructor was setting up the $this->registry object. You are overriding the constructor, which now does not set up that object anymore. Hence: you error out when the code is trying to use the expected object which is not there.
If you override a constructor, you should/need to invoke the original one as well:
public function __construct(...) {
parent::__construct(...);
// new code
}
You can make a constructor in controller or model like this way.
class ModelMyModel extends Model {
public function __construct($params) {
parent::__construct($params);
}
}
You can use constructor like this, same for Model also you can use, by passing parameter.
class ControllerCommonDashboard extends Controller {
public function __construct($params) {
parent::__construct($params);
}
}

Can't extend my Controller

I am trying to write an extension to my Controller class. The problem is I can't seem to figure out how..
I have the following class named test in which there is one function which simply returns aaaa and in in the same file, at the end, as my Controller:
class test extends Controller
{
function test()
{
parent::Controller();
}
function echoMe(){
return 'aaaaaaaaaaaaaaaaa';
}
}
Within my Controller class I have a function which is the general output for a clients homepage. I'm trying to call the function echoMe from the extension above, but I keep getting
Call to undefined method Controller::echoMe()
Here is the client function (the call to echoMe() is right at the top):
function controller_client1($controlData = NULL)
{
echo $this -> echoMe();
//as the client page is content from the xml, mmodel needs the page number
$pageNumber = '';
if(isset($_GET['number']))
{
$num = htmlentities($_GET['number']);
if(ctype_digit($num) && $num >= 0)
{
$pageNumber = $num;
}
}
else{
$pageNumber = 0;
}
//loading the page content
$data = $this->model->model_loadXMLdata($pageNumber);
if(!empty($controlData))
{
//check if there is any info in the control data sent
foreach($controlData as $key => $value)
{
//add the info to the data array
$data[$key] = $value;
}
}
$this->load->load_clientHomePage($data);
}
I know this is a very simple question. I've been trying to follow this guide, but something isn't clicking...
Could somebody please help? How can I call the function echoMe() from test?
I know how to write just a brand new class and call it, but I'm trying to learn how to extend properly and keep failing.
Am I meant to call the "test" from within the Controller somewhere?
In the config.php you set the prefix for the file you want to extend. So it should be My_test, unless you have changed this preset(displayed below)
/*
|--------------------------------------------------------------------------
| Class Extension Prefix
|--------------------------------------------------------------------------
|
| This item allows you to set the filename/classname prefix when extending
| native libraries. For more information please see the user guide:
|
| http://codeigniter.com/user_guide/general/core_classes.html
| http://codeigniter.com/user_guide/general/creating_libraries.html
|
*/
$config['subclass_prefix'] = 'MY_';
Make sure you have the controller in the right folder (application/core in codeigniter 2.1.0) then you shouldn't have a problem. Hope that helps
here is my controller that i extend. The file is called My_Controller.php (creative I know)
<?php
class MY_Controller extends CI_Controller {
function __construct()
{
parent::__construct();
//constructor code here
}
//Custom functions here
}
//sencond controller I extend in the same file
class MY_Admin extends CI_Controller {
function __construct()
{
//more custom stuff for admin stuff
}
//more custom functions for admin stuff
}
?>
Has you see I have two extended controllers in the same file.
My extending code looks like this:
<?php
class home extends MY_Controller
{
and then just replace My_Controller with My_Admin if I want to extend the admin.
echoMe() function is defined in test class and not in Controller class. When controller_client1 function is called with the instance of Controller class, echoMe does not exist because it is not defined within Controller class.
The best way to achieve this is to create empty echoMe function in base Controller class. This way polymorphism works. When calling controller_client1 function from instance of test class, method from that class will be executed. Otherwise, method from base class will be executed.
I hope I didn't miss the point of the question :)
echo $this -> echoMe(); will fail because its created in the child(extended) class and your calling it in the parent class. The question is a little hard to understand.
abstract class Controller{
public function __construct(){
}
public function echoMe($str){
echo $str;
}
}
class test extends Controller{
public function __construct(){
parent::echoMe('aaaaaaaaaa');
}
}
Try this (general idea, not CodeIgniter only):
$test = new test();
echo $test->echoMe();
Remember, test extends your Controller class, not the other way round - so you can't call your methods outside the test class/object instance.
Also, it might be a good idea to upgrade to a new version of CodeIgniter - beware of the new parent controller name, though.
EDIT
Ok, this should be enought to get you started - note that it's PHP5, not PHP4, so constructors are called __construct and not the class name:
class Controller {
public $mainvar;
function __construct() {
$this->mainvar = '<br />';
}
function echoMe() {
return 'aaaaaaaaaaaaaaaaa';
}
}
class Test extends Controller {
function __construct() {
parent::__construct();
}
function echoMeAgain(){
return 'bbb';
}
}
$test = new Test();
echo $test->echoMe();
echo $test->mainvar;
echo $test->echoMeAgain();
I think the question has actually already been answered by Kosta, but there might be some misunderstanding at your side. So let me extend that by some example code:
class Controller {
public function run() {
$this->echoMe();
}
}
class test extends Controller {
public function echoMe() {
echo "works";
}
}
// This does NOT work, because Controller::echoMe does not exist
$controller = new Controller();
$controller->run();
// This DOES work, because $this will be instance of test, and
// test::echoMe exists and is callable.
$test = new Test();
$test->run();
"extends" does not mean, that the actual Controller class gets extended. The new class "test" just inherits every single method and property that is not declared "private" from the Controller class. The Controller class itself remains untouched.

Categories