I'm trying to create some classes and i would like to use this syntax:
$my = new My();
$my->field()->test('test');
I know how to do a $my->test('test'), it's easy - but I don't know how to add a field() attribute to make an easier comprehension of my class in my code.
I can guess it's something like a class into another class - extends - but i'm not sure about that so if you know how to do something similar.
I precise it's only for a better comprehension into my class. I mean the aim is to categorize functions in this My class.
Thank you :)
If you break your php down a bit, you will understand what is going on. For example lets make this:
$my->field()->test('test');
into this (for clarification).
$newObject = $my->field();
$newObject->test('test');
From here you can observe that the return of the method $my->field() is actually an object with another method test which you can then call. It is called method chaining and can be useful at times.
Here is a test case:
class a{
public function My(){
return new b;
}
}
class b{
public function foo(){
echo 'hello bar';
}
}
$a = new a();
$a->My()->foo();
In order to carry out an action on a method the method needs to return an object.
class a {
public function b($c){
echo $c;
return $this;
}
}
would allow
$d = new a();
$d->b("foo")->b("bar");
$d->b("foo")->b("bar")->b("far")->b("tar");
Related
I have wrote this code by looking at similar code from a PHP cookbook. I have few troubles with executing and understanding it + it is not working well. Hope someone can help me.
<?php
class example {
//protected $a;
//protected $c;
public function NumberInput($number){
$this->a = $number;
}
public function NumberOutput(){
return $this->a;
}
}
class example2 {
public function __construct(){
$this->mergingclass = new example;
}
public function numberInput2($number){
$this->c = $number;
}
public function NumberOutput2(){
return $this->c;
}
public function __call($method,$arguments){
echo "called methos is $method <br> ";
;
return $this->x = $arguments;
}
}
$b = new example2;
$b->NumberInput(7);
echo $b->NumberOutput();
?>
so my questions are:
Why do I even need __construct function ? Code is working excatly the same with or without it. Or atleast I can't spot the difference with my newbie abilities. If I understand correctly it should agreggate objects but when I put it in comments nothing changes.
When I execute this code insted of number 7 I get "Array". I suppose number 7 is inside of that array, so how can I echo it ?
Thanks in advance.
First of all, __construct is like a magic method in PHP, that makes it possible to create an object out of class. Each time you write something like this:$myObject = new Object(); constructor of Object class is called by default and it creates object referenced by $myObject variable. So without that method in it, you will not be able to properly use classes and create objects.
use print_r($array) or var_dump($array) to see array structure
I have two classes A and B, where B extends A and adds some methods. I have a class C with a method that accepts A as parameter for generalization purposes. The issue is that once inside the method, I want to access the methods of class B on the object, but I'm not able to do so. Don't get error, but have null in the return, when I have dumped the object and know that it holds data.
Sorry if it's seems ridiculous, but I'm trying to use a bahaviour that you would expect in normal inheritance. Maybe be I'm missing something and it is my fault, but have no idea of what is happening here.
Please, if you have any idea of how to do this, help me.
Some code:
public function createProject(AssociatedProjectInterface $project_data){
if(!is_a($project_data, 'class\path\GithubProject')){
throw new InvalidArgumentException('The argument needs to be of type: GithubProject.');
}
$repo = $this->client->api('repo')->create(
$project_data->getTitle(),
$project_data->getDescription(),
null,
!$project_data->getIsPrivate(),
null,
$project_data->getIssuesEnabled(),
$project_data->getWikiEnabled());
}
Thanks.
Note that PHP's type checking is very loose. It calls the method of the class that is passed. The type checking is only taking place at the moment that function is called. So in the example below, testType must be past an object of type A or a descendant of A. After that initial check, no type checking is done at all! So the function can call any method declared in A or B. If a method is declared in both, it is considered overridden and the version in B is used.
<?php
class A {
function foo() {
echo 'A:foo';
}
}
class B extends A {
function foo() {
echo 'B:foo';
}
function bar() {
echo 'B:bar';
}
}
function testType(A $a)
{
$a->foo(); // B:foo
$a->bar(); // B:bar <- This will succeed even though there's no bar() in A.
}
$a = new B();
testType($a);
What you're asking for is NOT expected in normal object-oriented inheritance, but apparently works in PHP. Normally, if a method expects an object of class A, you can pass an object of class B that extends A, but the method will treat the object as though it were of class A. This means that when you call methods inherent to B, you are calling methods that don't exist and an error should be thrown.
In php though, momma don't care. As proof run the following minimal test:
<?php
class A {
public function foo() {
echo "in foo\n";
}
}
class B extends A {
public function bar() {
echo "in bar\n";
}
}
class C {
public function test(A $b) {
$b->foo();//works, because foo exists in the A class definition
$b->bar();//also works for B, but not A
}
}
$a = new A();
$b = new B();
$c = new C();
$c->test($b);
$c->test($a);//Will throw an error because the method bar() is not found
Note that it is considered extremely bad programming practice to ask for A when the code will quite literally die if it requires B. You should really avoid this situation.
I have a class that generates data based on a few things. I would like to format that data from the outside. So I am trying to pass a function into the class so that it would format that data. I have looked at many examples, but it seems this is unique.
Can anybody give an idea of how to do this? The following code gives an error.
<?php
class someClass {
var $outsideFunc; // placeholder for function to be defined from outside
var $somevar='Me'; // generated text
function echoarg($abc){
$outsideFunc=$this->outsideFunc; // bring the outside function in
call_user_func($outsideFunc,$abc); // execute outside function on text
echo $abc;
}
}
function outsidefunc($param){ // define custom function
$param='I am '.$param;
}
$someClass=new someClass();
$someClass -> outsideFunc = 'outsideFunc'; // send custom function into Class
$someClass -> echoarg($someClass->somevar);
$someClass -> outsidefunc = 'outsidefunc';
In PHP, function names are not case sensitive, yet object property names are. You need $someClass->outsideFunc, not $someClass->outsidefunc.
Note that good OOP design practice calls for the use of getter and setter methods rather than just accessing properties directly from outside code. Also note that PHP 5.3 introduced support for anonymous functions.
Yeah. You are right. Now there is no error. But it does not work either.
By default, PHP does not pass arguments by reference; outsidefunc() does not actually do anything useful. If you want it to set $param in the caller to something else, and do not want to just return the new value, you could change the function signature to look like this:
function outsidefunc(&$param) {
You would also need to change the way you call the function, as call_user_func() does not allow you to pass arguments by reference. Either of these ways should work:
$outsideFunc($abc);
call_user_func_array($outsideFunc, array(&$abc));
Why not pass your function as an argument?
<?php
class someClass {
public $somevar="Me";
public function echoarg($abc,$cb=null) {
if( $cb) $cb($abc);
echo $abc;
}
}
$someClass = new someClass();
$someClass->echoarg($someClass->somevar,function(&$a) {$a = "I am ".$a;});
i am not sure what exactly you are looking for, but what i get is, you want to pass object in a function which can be acheive by
Type Hinting in PHP.
class MyClass {
public $var = 'Hello World';
}
function myFunction(MyClass $foo) {
echo $foo->var;
}
$myclass = new MyClass;
myFunction($myclass);
OP, perhaps closures are what you're looking for?
It doesn't do EXACTLY what you're looking for (actually add function to class), but can be added to a class variable and executed like any normal anonymous function.
$myClass->addFunc(function($arg) { return 'test: ' . $arg });
$myClass->execFunc(0);
class myClass {
protected $funcs;
public function addFunc(closure $func) {
$this->funcs[] = $func;
}
public function execFunc($index) { $this->funcs[$index](); } // obviously, do some checking here first.
}
ok I do have the code below
<?php
class foo{
public $bar = NULL;
public function boo(){
$this->bar();
}
}
$mee = new foo();
//save a closure function on the property
$mee->bar = function(){
echo 'hahaha';
};
//invoke the closure function by using a class method
$mee->boo();
?>
and you can see it running here http://codepad.org/s1jhi7cv
now what i want here is to store the closure function on the class method.
well closures are possible as i read the documentation about it here http://php.net/manual/en/functions.anonymous.php
is this possible? did i went to something wrong? please correct me
Your example code at codepad.org does not work because codepad.org uses PHP 5.2.5, and closure support was only added in 5.3.
However, your code will also not work in a PHP version that supports closures, although you will get a different error: http://codepad.viper-7.com/Ob0bH5
This is a limitation of PHP at present. $obj->member() looks for a method named member and will not look at properties to see if they are callable. It is, frankly, annoying.
The only way I am aware of to make this work without call_user_func()/call_user_func_array() is:
public function boo() {
$func = $this->bar;
$func();
}
You need to exploit some magic functionality of PHP (__call) to make use of that. Extend from Extendable for example:
class Extendable {
static function import($context) {
$self = new static();
while (is_callable($context)) $context = $context($self);
if (is_array($context) || is_object($context) || is_a($context, 'Traversable')) {
foreach($context as $key => $value)
$self->$key = &$value; # preserve keys if
}
return $self;
}
public function __call($name, $args) {
if (isset($this->$name) && is_callable($this->$name)) {
return call_user_func_array($this->$name, $args);
}
throw new BadFunctionCallException(sprintf('Undefined function %s.', $name));
}
}
And you can do the job. It's not that nice. Background and examples are in one of my blog posts:
PHP: Extending stdClass with Closures (plus Visitor)
You can naturally implement that magic functionality your own, too.
Use call_user_func() function:
<?php
class foo{
public $bar = NULL;
public function boo(){
call_user_func($this->bar);
}
}
$mee = new foo();
//save a closure function on the property
$mee->bar = function(){
echo 'hahaha';
};
//invoke the closure function by using a class method
$mee->boo();
This will display "ahahah"
Hope it helps.
You will not be able to do that.
Take for example this code:
class T {
function foo() {
echo 'T::foo';
}
}
$t = new T;
$t->foo = function() {
echo 'Closure::foo';
};
$t->foo();
It works fine on PHP 5.4.6 and/or PHP 5.3.16, however it will result in T::foo getting printed.
This happens because methods, in PHP, are not modifiable class properties, as they are for example in javascript.
However,
$foo = $t->foo;
$foo();
will print Closure::foo as expected.
PHP is not a prototype based language hence you cannot redefine functions
Use __call to catch all non-defined methods and then look up the closure and invoke it. Take a look at my post on this SitePoint thread.
Starting at php 7, you can put round brackets around the instance and method to call the method like so: ($this->bar)();.
This appears to cause a syntax error on earlier versions however.
http://codepad.viper-7.com/ezvlkQ
So, I'm trying to figure out:
...?php
$object = new A();
class A
{
static public $foo = 'bar';
function displayFoo()
{
echo $this->$foo;
}
}
A::displayFoo();
A->displayFoo();
?>
About this, how many errors can you find? Can you tell me what they are in real human terms? I can't really interpret what is and what is not okay from the validator that codepad uses...
I’ve updated your code here http://codepad.viper-7.com/UaUE4g
Error 1:
echo $this->$foo;
This should read:
echo self::$foo;
.. as it is static.
Error 2:
A::displayFoo();
The method is an instance method :: is used for access to static methods.
Error 3:
A->displayFoo();
This is an error because A is undefined and if it was it should have read $A. This would be okay:
$object->displayFoo();
.. as $object is an instance of class A.
Next step, consult the manual on the topic static.
Not sure where to start. Static methods belong to the class, normal methods belong to an object, an instantiation of that class. For example, you can have:
Class A {
static public $foo = 'WOOHOOO';
static function displayFoo() {
echo self::$foo;
}
}
echo A::displayFoo();
This works because you're calling the displayFoo method belonging to class A. Or you can do this:
Class A {
public $foo = "WOOHOO";
public function displayFoo() {
echo $this->foo;
}
}
$obj = new A();
$obj->displayFoo();
Now you're creating an object based on the class of A. That object can call its methods. But the object doesn't have static methods. If you were to declare the function static, it would not be available to $obj.
You can't do:
A->displayFoo()
at all, under any circumstances, ever. The -> operator assumes an object, and A can't be an object because its not a variable.
You can read up on static class members in the manual here:
http://php.net/static
Pay close attention to the examples.