PHP: Calling a private method from within a class dying badly - php

So this might sound a little convoluted. Fingers crossed I come across clearly.
I'm working in an MVC framework in PHP.
I load a controller /report/index which calls to a helper
<? class ReportController extends Controller {
public function index() {
$foo = MainReport::get_data($_REQUEST);
}
}
?>
Inside the helper
<? class MainReport extends foo {
public function get_data($_REQUEST) {
// do stuff
return $stuff_done;
}
}
?>
It I run it like ^this all's well and good. Unfortunately, I want to run it like this:
<? class MainReport extends foo {
private function do_stuff() {
// do even better stuff here!
return $better_stuff;
}
public function get_data($_REQUEST) {
// do stuff
$x = $this->do_stuff();
}
}
?>
Unfortunately... when I try and call a private function from within a class that I've called from elsewhere... (whew, that's a mouthful) ... everything dies. Dies so very very badly that I don't even get an error.
It seems obvious to me that I'm having an incredibly dorky sort of syntax issue of some sort... but how do I correctly access private functions from within a class?
Maybe something like:
self::do_stuff();
What about declaring and accessing private class variables?
private $bar = array();
Any help would be welcome.

You are calling your function from a static context,
MainReport::get_data($_REQUEST)
therefore $this does not exist while inside that function.
If you want to call another class function while inside a static context, you have to also call it statically.
i.e.
public function get_data($_REQUEST) {
// do stuff
$x = MainReport::do_stuff();
}
Alternatively, you can create an instance of your class in the original call and use the instance:
$myMainReport = new MainReport();
$myMainReport->get_data($_REQUEST);
Then your class code will work as expected

I've just found that self:: does work as well
if I want to have private class variables, I can declare and access them using
private static $foo
and
self::$foo = "foo";
additionally a private function can be accessed with
self::function_foo();

Related

Tell phpunit to call public instead of private

My Question is. I have a class i want to test (myClass). In myClass there is a function wich calls a private function thats also in the myClass.
I know i can't test private functions. Is it possible to tell phpunit to call another function instead of the private?
Example
$this->testclass is now the class i want to test
$this->testclass = new \stdClass();
$this->testclass->mock = $this->getMockBuilder('myClass')->getMock();
Outside my testcase i have created a fake class.
$this->mockextended = new \stdClass();
$this->mockextended->mock = new MOCKEXTENDEDCLASSES();
in the $this->mockextended i have a public function.
the function i want to test
public function TestMe(){
$this->somePrivateFunctioniHate(); <==== this is the pain in my ass
}
and the private function
private function somePrivateFunctioniHate(){
//come code
}
What i want to do is. the function TestMe is calling a private function.
Is it possible to tell phpunit to override the private function and call another function thats inside $this->mockextended;
I have tried it like this.
$this->testclass->somePrivateFunctioniHate() = $this->mockextended->theWholeNewPrivateFunction()
only this gives me a nice error. I did this before and it worked. Called it like this
EDIT
For people who don't understand my question.
I have another function that calls another class. I din't want to have another class in my test so i created a fake Class outside my testcase. Inserted the same functions as the class the function wants to include. Did it like this
$this->testclass->chunks = new \stdClass();
//MOCKchunckTpl is the fake class outside my testcase
$this->testclass->chunks->config = new MOCKchunkTpl();
This works. Whenever a function wants to call $this->testclass->chunks->config->Somefunction(); it will be redirected to my fake class.
BUT when i try to do the same with a function thats calling a private function. Like $this->testclass->somePrivateFunctioniHate() = $this->mockextended->theWholeNewPrivateFunction() it gives a nice error
Fatal error: Can't use method return value in write context in
Short answer: No, there isn't. There is no way for PHPUnit to manipulate private methods.
Mocks are for faking the behavior of classes, which depend on the class you want to test. If you need to overwrite a private method, there is something wrong in your architecture. Private methods should be tested by simple testing the public methods in which they are used. If you need to test it separately, declare it public.
EDIT: Here is an example how you'd test a simple code using a private method or putting this private method in another class:
1. Private method
class MyClass {
public function myMethod() {
return $this->myPrivateMethod();
}
private function myPrivateMethod() {
return 2;
}
}
And the test class:
class MyClassTest extends \PHPUnit_Framework_TestCase {
public function testMyMethod() {
$myClass = new MyClass();
// don't mind the private method, just test if the public method is working
$this->assertEquals(2, $myClass->myMethod());
}
}
1. Second class
class MyClass {
public $dependentClass;
public function myMethod() {
return $this->dependentClass->dependentMethod();
}
}
And the dependent class:
class DependentClass {
public function dependentMethod() {
return 38943;
}
}
Testing MyClass with the DependentClass:
class MyClassTest extends \PHPUnit_Framework_TestCase {
public function testMyMethod() {
$dependentMock = $this->getMockBuilder("DependentClass")->getMock();
$dependentMock->expects($this->any())
->method("dependentMethod")
->willReturn($this->returnValue(2));
$myClass = new MyClass();
$myClass->dependentClass = $dependentMock;
$this->assertEquals(2, $myClass->myMethod());
}
Although we defined a whole other return in DependentClass, the test will still pass, because we mocked it and are able to define every behavior we'd expect DependentClass to have.
But to cleanly test the project, we need to define another test for DependentClass as well to test, if this class is working. This test should fail if it is not working anymore, not the test for MyClass.

Trying to understand PHP OOP

I'm wondering why the following code won't print out anything. I'm trying to access Bar::$some_var from method in parent class. Where Bar::$some_var is defined in it's constructor.
I've tried using self::$some_var and static::$some_var in Foo::hello() but neither worked. Do I have to make $some_var static?
class Foo {
private $some_var;
public function __construct() {
$this->some_var = 5;
}
public function hello() {
print $this->some_var;
}
}
class Bar extends Foo {
public function __construct() {
$this->some_var = 10;
}
}
$bar = new Bar();
$bar->hello();
Thanks in advance.
private makes a member variable unavailable outside of a class. You need to use protected to allow extending classes to have access to that variable.
protected $some_var;
See Visibility
Your class variable cannot be private if you would like your child class to access it.
Try protected instead and it should work!
:: operator is used to access class items (constants, static
variables, static methods)
-> operator is used to access object items (non static properties and methods)
anyway in your code the problem is visibility of $some_var. It has to be almost protected, public will also work

How can a PHP class that extends another inherit a private function?

I am trying to extend a PHP class without rewriting the whole thing. Here is an example:
<?
$a = new foo();
print $a->xxx();
$b = new bar();
print $b->xxx();
class foo {
const something = 10;
public function xxx() {
$this->setSomething();
return $this->something;
}
private function setSomething() {
$this->something = self::something;
}
}
class bar extends foo {
public function xxx() {
$this->setSomething();
$this->something++;
return $this->something;
}
}
?>
However when I run the script I get the following error:
Fatal error: Call to private method foo::setSomething() from context 'bar' in test.php on line 23
It would seem that bar is not inheriting the private function setSomething(). How would I fix this without modifying the foo class?
No, you can not fix this without modifying the foo class. Because an inherited class can not access parent class's private members. It's a very basic oop rule.
Declare setSomething() as protected. It'll be solved.
See manual
Private members are not inheritable, you can not use them in sub class. They are not accessible outside the class.
You must need to make that function as protected or public. Protected members are accessible to that class and for the inherited class. So, your best bet is to make that function Protected.
bar is inheriting the function alright, but it can't call it. That's the whole point of private methods, only the declaring class can call them.
Try reflection
http://php.net/manual/en/class.reflectionclass.php
Also:
Call private methods and private properties from outside a class in PHP
Did you try this?
class bar extends foo {
public function xxx() {
$this->something = parent::xxx();
$this->something++;
return $this->something;
}
}
Note the parent::xxx(); is public, so it should work... even though it looks like a static call.
Without modifying the original class, there is no way for the inherited class to directly call private methods of the parent class.

How to call static func by passing $_GET params?

i have got a static function> which is called
regenerateThumbnailsCron()
And I would like to execute this function by GET params, for example>
if($_GET["pass"]=="password")
self::regenerateThumbnailsCron();
But if I tryied to call this function in constructor>
class AdminImages extends AdminTab
...
public function __construct()
{
if($_GET["pass"]=="password")
self::regenerateThumbnailsCron();
}
I cannot execute this function.
Is any way, how to call this function before __construct to correctly execute?
Thanks very much for any advice.
EDIT>
I tried also with public function>
<?php
include 'AdminImages.php';
$images = new AdminImages();
$images->regenerateThumbnailsCron();
?>
But i got error>
Fatal error: Class 'AdminTab' not found
You need to do a include 'AdminTab.php'; as well, since your class extends that
Not completely sure I understand your question, are you saying that you have static class "B" which extends class "A", "A" having your regenerateThumbnailsCron() method which you want to call before anything else?
If so then try this:
<?php
class A {
private function regenerate() {
.... do something ....
}
}
class B extends A {
function __construct() {
if ($_GET["pass"] == "password") {
parent::regenerate();
}
}
function regenerateThunbnailsCron() {
.... do somethinig ....
}
}
$images = new B();
$images->regenerateThumbnailsCron();
?>
This way, your parent's "regenerate()" function would get called during the constructor. You can switch this around to be a static class if you want, which if your goal is to compartmentalise any variables and functions away from the global scope would be a better way.

call a static method inside a class?

how do i call a static method from another method inside the same class?
$this->staticMethod();
or
$this::staticMethod();
self::staticMethod();
More information about the Static keyword.
Let's assume this is your class:
class Test
{
private $baz = 1;
public function foo() { ... }
public function bar()
{
printf("baz = %d\n", $this->baz);
}
public static function staticMethod() { echo "static method\n"; }
}
From within the foo() method, let's look at the different options:
$this->staticMethod();
So that calls staticMethod() as an instance method, right? It does not. This is because the method is declared as public static the interpreter will call it as a static method, so it will work as expected. It could be argued that doing so makes it less obvious from the code that a static method call is taking place.
$this::staticMethod();
Since PHP 5.3 you can use $var::method() to mean <class-of-$var>::; this is quite convenient, though the above use-case is still quite unconventional. So that brings us to the most common way of calling a static method:
self::staticMethod();
Now, before you start thinking that the :: is the static call operator, let me give you another example:
self::bar();
This will print baz = 1, which means that $this->bar() and self::bar() do exactly the same thing; that's because :: is just a scope resolution operator. It's there to make parent::, self:: and static:: work and give you access to static variables; how a method is called depends on its signature and how the caller was called.
To see all of this in action, see this 3v4l.org output.
This is a very late response, but adds some detail on the previous answers
When it comes to calling static methods in PHP from another static method on the same class, it is important to differentiate between self and the class name.
Take for instance this code:
class static_test_class {
public static function test() {
echo "Original class\n";
}
public static function run($use_self) {
if($use_self) {
self::test();
} else {
$class = get_called_class();
$class::test();
}
}
}
class extended_static_test_class extends static_test_class {
public static function test() {
echo "Extended class\n";
}
}
extended_static_test_class::run(true);
extended_static_test_class::run(false);
The output of this code is:
Original class
Extended class
This is because self refers to the class the code is in, rather than the class of the code it is being called from.
If you want to use a method defined on a class which inherits the original class, you need to use something like:
$class = get_called_class();
$class::function_name();
In the later PHP version self::staticMethod(); also will not work. It will throw the strict standard error.
In this case, we can create object of same class and call by object
here is the example
class Foo {
public function fun1() {
echo 'non-static';
}
public static function fun2() {
echo (new self)->fun1();
}
}
call a static method inside a class
className::staticFunctionName
example
ClassName::staticMethod();

Categories