Please take a look at this code:
class Foo {
public $barInstance;
public function test() {
$this->barInstance = new Bar();
$this->barInstance->fooInstance = $this;
$this->barInstance->doSomethingWithFoo();
}
}
class Bar {
public $fooInstance;
public function doSomethingWithFoo() {
$this->fooInstance->something();
}
}
$foo = new Foo();
$foo->test();
Question: is it possible to let the "$barInstance" know from which class it was created (or called) without having the following string: "$this->barInstance->fooInstance = $this;"
In theory, you might be able to do it with debug_backtrace(), which as objects in the stack trace, but you better not do it, it's not good coding.
I think the best way for you would be to pass the parent object in Bar's ctor:
class Foo {
public $barInstance;
public function test() {
$this->barInstance = new Bar($this);
$this->barInstance->doSomethingWithFoo();
}
}
class Bar {
protected $fooInstance;
public function __construct(Foo $parent) {
$this->fooInstance = $parent;
}
public function doSomethingWithFoo() {
$this->fooInstance->something();
}
}
This limits the argument to being proper type (Foo), remove the type if it's not what you want. Passing it in the ctor would ensure Bar is never in the state when doSomethingWithFoo() would fail.
Related
guys lets say we have this class: all i want to do is to use a specific function to do something, think it as a button, but in a way that you have 1 public function and you can execute parts of it!
CLASS DATA {
public function X() {
function A() {
//do_something
}
}
}
and now i'm in the index.php and i want to call the function A() only.
i tried $data->X()->A() but nothing
i tried $data->X(A()) also nothing
is it possible this?
In the way you've written it, no. Looks to me like you're trying to build something in the way you would a Javascript application. But like Rizier123 points out you could do something like this.
class Foo {
public function getBar(){
return new Bar();
}
}
class Bar {
public function someFunction() {
}
}
$foo = new Foo();
$foo->getBar()->someFunction();
Although I'm not entirely sure why you would want to nest things that way when inheriting would be a better route. Something like this:
class Foo extends Bar {
}
class Bar {
public function someFunction() {
}
}
$foo = new Foo();
$foo->someFunction();
But I guess you could use the former as a way to pass specific constructor parameters in a consistent manor.
class Foo {
public function getRainbow(){
return new Bar('rainbow');
}
}
class Bar {
private $type;
public function __construct($type)
{
$this->type = $type;
}
public function someFunction() {
switch($this->type){
case 'rainbow':
echo 'All the way across the sky.';
break;
default:
echo 'Boring.';
break;
}
}
}
$foo = new Foo();
$foo->getRainbow()->someFunction();
How can I create something like
MyObject->property->method()
in PHP?
I only know how to create a method for a class:
class MyObject
{
public function MyMethod()
{
// do something
}
}
In Javascript I can easily do something like
var MyObject = {
property : {
method : function ()
{
// do something
}
}
}
How do I do that?
In Javascript you can create objects and methods inline, in PHP you need to have a class and instantiate it:
class Foo {
public function method() {}
}
class MyObject {
public $property;
public function __construct() {
$this->property = new Foo;
}
}
$o = new MyObject;
$o->property->method();
You can set an object as the value of a property. Something like this:
class Foo {
public $Bar;
public function __construct() {
$this->Bar = new Bar();
}
}
class Bar {
public function ShowBar() {
echo 'Bar';
}
}
$Foo = new Foo();
$Foor->Bar->ShowBar();
As others have correctly answered, this works differently in PHP and Javascript. And these differences are also the reason why in PHP you need to define the class methods before you run them. It might become a bit more dynamic in the future but I'm sure not on the level of Javascript.
You can however fake this a bit in PHP because you can assign functions to properties dynamically:
$myObject = new PropCall;
$myObject->property->method = function() {
echo "hello world\n";
};
$myObject->property->method();
This example outputs:
hello world
This does work because some little magic has been added in the instantiated object:
class PropCall
{
public function __call($name, $args) {
if (!isset($this->$name)) {
return null; // or error handle
}
return call_user_func_array($this->$name, $args);
}
public function __get($name) {
$this->$name = new PropCall;
return $this->$name;
}
}
This class code checks if a dynamic property has been added with the name of the method called - and then just calls the property as a function.
I am trying to access the results of a function that is public inside another class, but I'm not entirely sure how to do this. The class i'm trying to access require parameters, so the class_name::function() method is not working. I'm still new to working with classes, and trying to learn it.
Class one:
class foo {
private $var1;
function __construct($param) {
$this->var1 = $param
}
public function myFunc() {
echo $this->var1;
}
}
Class 2
class bar {
public function secondFunc() {
var_dump(**RESULT FROM foo->myFunc HERE);
}
}
These two classes are a basic example of what i'm actually doing, but from this you should get the general idea of my question.
For the correct result to display, the first class needs the params passed to it otherwise the function fails.
I tried using foo::bar(), but this doesn't pass any params to the first class, and it therefor fails.
So, how do I access myFunc from foo inside secondFunc from bar?
You have to pass an instance of foo to bar:
class Foo {
private $var1;
function __construct($param) {
$this->var1 = $param
}
public function myFunc() {
return $this->var1;
}
}
class Bar {
private $foo;
function __construct(Foo $foo) {
$this->foo = $foo
}
public function secondFunc() {
var_dump($this->foo->myFunc());
}
}
$bar = new Bar(new Foo('something'));
$bar->secondFunc();
Is that what you want?
Your example isn't very practical but here is the basic idea
public function secondFunc($dependency) {
var_dump($dependency->myFunc());
}
or...
public function secondfunc() {
$foo = new foo();
var_dump($foo->myFunc();
}
What about
class bar {
public function secondFunc() {
$foo = new foo($param);
var_dump($foo->myFunc());
}
}
Or do you need something in one line?
What would be the best practice to do this :
class AwesomeClass {
// Code
public function test()
{
foreach($objects->values as $v)
{
New SuperClass($v);
}
return $objects;
}
}
class SuperClass {
public function __construct($arg2)
{
return trim($arg2);
}
}
$rule_the_world = New AwesomeClass($arg1);
$king = $rule_the_world->test();
The previous code is obviously not working, I think I'm missing some major point of PHP OO.
It's very difficult to decipher what you're asking for, and the code you have is not recoverable.
Code Errors
There are several errors in your code that are illogical:
AwesomeClass has no constructor.
This makes passing arg1 to new AwesomeClass meaningless
arg1 is never initialized
In AwesomeClass::test(), objects is never initialized and has no member value.
You will get a warning since it's not traversable
New SuperClass (should be new, per standards) does nothing.
__construct() cannot return a value.
What You May Want
What I think you're going for is something like this:
class AwesomeClass implements IteratorAggregate {
private $arg1;
public function __construct(array $arg1) {
$this->arg1 = $arg1;
}
public function getIterator() {
return new ArrayIterator($this->arg1);
}
}
class SuperClass {
private $arg2;
public function __construct($arg2) {
$this->arg2 = $arg2;
}
public function __toString() {
return "$this->arg2\n";
}
}
$rule_the_world = new AwesomeClass(array('one', 'two', 'three'));
foreach ($rule_the_world as $sc) {
$sc = new SuperClass($sc);
echo $sc;
}
Note that it is redundant to create an ArrayIterator instance when arg1 must already be an array, this is just an example.
sorry for that weird subject but I don't know how to express it in an other way.
I'm trying to access a method from a calling class. Like in this example:
class normalClass {
public function someMethod() {
[...]
//this method shall access the doSomething method from superClass
}
}
class superClass {
public function __construct() {
$inst = new normalClass;
$inst->someMethod();
}
public function doSomething() {
//this method shall be be accessed by domeMethod form normalClass
}
}
Both classes are not related by inheritance and I don't want to set the function to static.
Is there any way to achieve that?
Thanks for your help!
You can pass a reference to the first object like this:
class normalClass {
protected $superObject;
public function __construct(superClass $obj) {
$this->superObject = $obj;
}
public function someMethod() {
//this method shall access the doSomething method from superClass
$this->superObject->doSomething();
}
}
class superClass {
public function __construct() {
//provide normalClass with a reference to ourself
$inst = new normalClass($this);
$inst->someMethod();
}
public function doSomething() {
//this method shall be be accessed by domeMethod form normalClass
}
}
You could use debug_backtrace() for this. It is a bit iffy but for debugging purposes it is usefull.
class normalClass {
public function someMethod() {
$trace = debug_backtrace();
$trace[1]['object']->doSomething();
}
}
You have a few options. You can use aggregation like so
class normalClass
{
protected $superClass;
public function __construct( superClass $superClass )
{
$this->superClass = $superClass;
}
public function someMethod()
{
$this->superClass->doSomething();
}
}
class superClass
{
public function __construct()
{
$inst = new normalClass( $this );
$inst->someMethod();
}
public function doSomething()
{ //this method shall be be accessed by domeMethod form normalClass
}
}
Or just a straight-up setter
class normalClass
{
protected $superClass;
public function setSuperClass( superClass $superClass )
{
$this->superClass = $superClass;
}
public function someMethod()
{
if ( !isset( $this->superClass ) )
{
throw new Exception( 'you must set a superclass' );
}
$this->superClass->doSomething();
}
}
class superClass
{
public function __construct()
{
$inst = new normalClass();
$inst->setSuperClass( $this );
$inst->someMethod();
}
public function doSomething()
{ //this method shall be be accessed by domeMethod form normalClass
}
}
Depending on your use case, you might want to pass the instance to the function only:
class normalClass {
public function someMethod($object) {
$object->doSomething();
}
}
If normalClass::someMethod() can be called by multiple, distinct $objects, this might be the better choice (instead of providing the $object to the whole normalClass instance).
But regardless of that you might consider creating an Interface to use for type hinting:
interface ISomethingDoer {
public function doSomething();
}
class normalClass {
public function someMethod(ISomethingDoer $object) {
# Now PHP will generate an error if an $object is passed
# to this function which does not implement the above interface.
// ...
class superClass implements ISomethingDoer {
// ...
woah I had the same problem than you but instead of going with the so simple pass the reference to the object, I went with an event manager, Basically, when something would happen in the normal class, it would trigger an event which was listened by a class and that said class(the listener) would call the super class to execute that functionality and if necessary pass it new arguments.
Anyways, whether you pass it as a parameter to your object or you go with an event based approach, both solutions work. Choose the one you prefers.
For more information on events, sympony explains it quite good.
http://symfony.com/doc/current/components/event_dispatcher/introduction.html