This is what I have in foo.php
class Foo
{
public $foo = NULL;
public $foo2 = NULL;
public function setFoo ($foo, $foo2)
{
$this->foo = $foo;
$this->foo2 = $foo2'
}
}
This is what I have in foo3.php
class Foo3 extends Foo
{
public $foo3 = NULL;
public function setFoo3 ($foo3)
{
$this->foo = $foo3;
}
}
This is how I require it in my third file run.php:
require_once "foo.php";
require_once "foo3.php";
$foo = new Foo();
$foo->setFoo3("hello");
I get this error:
Fatal error: Call to undefined method Foo::setFoo3()
I'm not sure if the problem is how I'm requiring them. Thanks.
In your example, you are instantiating Foo, which is the parent and has no knowledge of the method setFoo3(). Try this:
class Foo3 extends Foo
{
...
}
require_once "foo.php";
require_once "foo3.php";
$foo = new Foo3();
$foo->setFoo3("hello");
At the first, in your foo.php shouldn't mark your fields public, because you set those values inside setFoo($foo1, $foo2) method. Instead, you may have something like:
<?php
class Foo
{
private $foo1;
private $foo2;
public function setFoo($foo1, $foo2) {
$this->foo1 = $foo1;
$this->foo2 = $foo2;
}
}
Then you should add extends keyword when declaring class Foo3, and another thing you need to include extending class file in the beginning of the file. In your case you may have something like the following in your foo3.php file:
<?php
require_once "foo.php";
class Foo3 extends Foo
{
public function setFoo3($foo3) {
$this->setFoo($foo3, "some foo3 specific value"); // calling superclass method
}
}
then you can create an instantiate of a Foo3 class in your run.php like so:
<?php
require_once "foo3.php";
$foo3 = new Foo3();
$foo3->setFoo3("bar");
and my advice, you should read a little about OOP techniques ;)
Of course that doesn't work. You've created a Foo object, and then tried to call foo3 on it. But Foo doesn't have a foo3 method.
Related
I have large class foo, that I want to split to two separate classes (and files);
My class foo uses contruct function and noumerous $this references.
I need a second class bar to be an extension for original foo class, so I could still use contruction with additional parameter if to include bar class;
$includeBar = true;
$foo = new foo($config, $includeBar);
I've tried putting it this way:
Class bar extends foo {
public function barFunction(){
//some function of bar
}
}
Class foo {
public function __construct($config, $includeBar = true) {
if ($includeBar) {
include_once 'bar.php';
}
}
}
But when I call:
$foo = new foo($config, true);
$foo->barFunction();
It fails, saying
PHP Fatal error: Uncaught Error: Call to undefined method foo::barFunction()
What am I doing wrong? pls help, got stuck
It should be the other way round.
Bar is your base class, that contains all the methods that every sub class also needs. Foo is the extention, the extras, so Foo extends Bar.
<?php
// file bar.php
Class Bar {
public function __construct($config) {
$this->config = $config;
}
public function barFunction() {
echo "I'm everybody ".$this->config['msg'];
}
}
// file foo.php
require_once('bar.php');
Class Foo extends Bar {
public function fooOnly() {
echo "I'm foo ".$this->config['msg'];
}
}
// consuming file index.php
include('foo.php');
$config = array('msg'=>'and I need coffee');
$foo = new foo($config);
$foo->barFunction(); // we can call this, because foo extends bar
// this won't work:
$bar = new Bar($config);
$bar->fooOnly();
// but this:
$bar->barFunction();
$foo->fooOnly();
(all the includes/requires can be omitted when using a proper autoloader!)
If you want reuse class methods or separate class method implementation I think you can use trait and then you can use keyword use to require functions to your class.
For example:
<?php
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>
The above example will output:
Hello World!
I have a few questions:
so, I have a class A as follows:
class A {
protected $ _blah = 'blah';
public __construct {
$this-> setPath ('test');
new B;
}
public setPath ($ path) {
$ This -> _ blah = $ path;
}
}
I have a Class B as follows:
class B extends A {
`echo $ this -> _ blah`;
}
nah, why is the output: 'blah' and not 'test' in class B.
however, I have changed the variable in class A to 'test' before my instance of class B.
From the code you posted, the problem is likely because you are calling $This instead of $this.
For reference, have a look at how PHP handles object inheritance. Because variables are case sensitive, you are not actually changing the property of your class in the posted code.
A better example would be the following:
class A
{
public $property = 'foo';
}
class B extends A
{
public function __construct()
{
$this->property = 'baz';
}
}
// 'foo';
echo A::$property;
$b = new B;
// 'baz'
echo $b->property;
OK - What I'm trying to do is kind of convoluted and I'm not sure if its even possible or if there is another "proper" way to do this but here it is in a nutshell:
class foo {
var $testvar = "foo";
function doTest() {
echo $this->testvar . "\n";
$t = new bar;
$t->updateParent();
echo $this->testvar;
}
}
class bar extends foo {
function updateParent() {
$this->testvar = "bar";
}
}
/*
What I get:
foo
foo
What I want:
foo
bar
*/
The reason I'm doing this is I'm designing a template engine and basically for my purposes the foo class is the main class that has the bulk of my application code. The system is designed so the users can create their own template php files which are loaded by the application within the context of a foo method. I want to set all the properties and methods of foo to private save for certain ones that will be protected and thus accessible to bar. The point being I want the users template php code to have access to only a limited number of functions of the parent class when I include their code.
A better example would be:
class foo {
protected $db;
private $settings;
function SomeAction() {
// some code that results in a template needing to be loaded
// code that determines the template file
$template = new bar;
$template->loadTemplate($file);
}
}
class bar extends foo {
function loadTemplate($file) {
//if file exists
require($file);
// has access $db driver class (without creating a new instance of it)
// does not have access to the $settings property
}
}
Any Ideas?
It seems strange to me that you are extending the foo class just to give access of $db may be some more properties. but this doesn't make sense to me. You should pass the dependency to both classes.
class foo {
protected $db;
private $settings;
function SomeAction(bar $bar) {
// some code that results in a template needing to be loaded
// code that determines the template file
$bar->loadTemplate($file);
}
}
class bar {
function loadTemplate($file, Gateway $db) {
// use $db here
//if file exists
require($file);
}
}
I believe you're looking for parent
Give this a try:
class foo {
var $testvar = "foo";
function doTest() {
echo $this->testvar . "\n";
$t = new bar;
$t->updateParent();
echo $this->testvar;
}
}
class bar extends foo {
function updateParent() {
parent::testvar = "bar";
}
}
/*
What I get:
foo
foo
What I want:
foo
bar
*/
try this
<?php
class foo {
var $testvar = "foo";
function doTest() {
echo $this->testvar . "\n";
$R =$this->updateParent();
echo $R;
}
}
class bar extends foo {
function __construct()
{
parent:: doTest();
}
function updateParent() {
$testvar = "bar";
return $testvar;
}
}
$t = new bar;
Instead of using the literal name of the base class in your code, you should be using the special name parent, which refers to the name of your base class as given in the extends declaration of your class
Every object instance is also an instance of it's parent.
You make all properties private in the parent and offer secured access through public methods. All public methods will be available to child classes as if they were their own, without access to private properties.
class foo {
private $db;
public function dbSelect() {
return $this->db->select();// Example
}
}
class bar extends foo {
public function loadTemplate($file) {
require($file);
$selected = $this->dbSelect();
}
}
<?php
class Foo {
private function FooFunction(){
}
}
class Bar extends Foo {
public function BarFunction(){
$this->FooFunction();
}
}
$foo = new Foo();
$foo->FooFunction(); //Fatal error: Call to private method Foo::FooFunction()
//(Fair enough)
$bar = new Bar();
$bar->BarFunction(); //Fatal error: Call to private method Foo::FooFunction()
//from context 'Bar'
I'm having some difficulty understanding how to properly declare functions in a class which can then be used in an extension of that class
When I instantiate Foo I'd like FooFunction to remain private.
However, I do need to be able to call it from within Bar.
change code as below:
<?php
class Foo {
protected function FooFunction(){
}
}
class Bar extends Foo {
public function BarFunction(){
$this->FooFunction();
}
}
private methods not accessable in child class.
you need to use protected method type.
I would like to do something like:
library.php:
require_once "laucher.php";
class Test{
public function __construct(){
print "test";
}
}
class Foo extends Bar{
public function __construct(){
$t = new Test();
}
}
class Bar{
public function __construct(){
}
}
And in laucher.php, I would like to create a Foo object as $t = new Foo();
How Can I create Foo Objects in laucher.php? I would like to create an "auto-laucher" of Foo();
You have to include the file Foo is located in. So...
include("foo_file.php");
Then you can instantiate Foo.
$my_object = new Foo();
You cannot create Foo objects before Foo has been defined. Therefore you can't create Foo objects inside "laucher.php" if you include it before the class declarations.
However, if laucher.php is included after the class declarations you should be able to create Foo objects inside. So I think this would work:
class Test{
public function __construct(){
print "test";
}
}
class Foo extends Bar{
public function __construct(){
$t = new Test();
}
}
class Bar{
public function __construct(){
}
}
require_once "laucher.php";