<?php
try{
$test = new TestAccessModifiers("2345","xyz","vfd","a0001","99","67"); /*invoking the class*/
var_dump($test->calculate());
}
catch(Exception $e){
echo $e->getMessage();
}
?>
<?php
class TestAccessModifiers {
function TestAccessModifiers($user_p,$user_fn,$user_ln,$user_id,$marks1,$marks2) {
echo "hello1";
$this->user_phone=$user_p;
$this->user_fname=$user_fn;
$this->user_lname=$user_ln;
$this->user_id=$user_id;
$this->marks1=$marks1;
$this->marks2=$marks2;
echo $this->marks1;
}
private $additional_marks = 10;
public static function calculate(){
return $this->marks1+$this->marks2+$this->getAdditionalmarks();
}
public function getAdditionalmarks(){
return $this->additional_marks;
}
}
?>
Above is the simple code i am trying to run... but i am unable to call TestAccessModifiers
I have tried using _constructor too
Rename your TestAccessModifiers function to __construct.
public function __construct($user_p,$user_fn,$user_ln,$user_id,$marks1,$marks2) {
echo "hello1";
$this->user_phone = $user_p;
$this->user_fname = $user_fn;
$this->user_lname = $user_ln;
$this->user_id = $user_id;
$this->marks1 = $marks1;
$this->marks2 = $marks2;
echo $this->marks1;
}
Then, remove static from calculate function.
It should then works..
Reference: http://php.net/manual/en/language.oop5.decon.php
if you are calling the class in another php page, make sure you include it like this.
include('/path/to/your/class.php');
$test = new TestAccessModifiers("2345", "xyz", "vfd", "a0001", "99", "67");
or if you are instantiating the object within the same file then place the instantiation code below your class.
class TestAccessModifiers {
public function __construct($user_p, $user_fn, $user_ln, $user_id, $marks1, $marks2) {
echo "hello1";
$this->user_phone = $user_p;
$this->user_fname = $user_fn;
$this->user_lname = $user_ln;
$this->user_id = $user_id;
$this->marks1 = $marks1;
$this->marks2 = $marks2;
echo $this->marks1;
}
private $additional_marks = 10;
public function calculate() {
return $this->marks1 + $this->marks2 + $this->getAdditionalmarks();
}
public function getAdditionalmarks() {
return $this->additional_marks;
}
}
try {
$test = new TestAccessModifiers("2345", "xyz", "vfd", "a0001", "99", "67"); /*invoking the class*/
var_dump($test->calculate());
} catch (Exception $e) {
echo $e->getMessage();
}
you have defined a static method in your class, and have used the pseudo variable $this inside of the static method, which PHP does not allow. since static method is treated out of object context in PHP. you need to remove the static method to use $this
First: Which PHP version you have?
Second: Are you including the class file in the file that you are instancing?
Third: Your function "calculate" is static, then, you can't access to it from an instance and it have no way to read or write properties non-statics.
Try TestAccessModifiers::calculate(); and put in a simple return "Hello World"
Greetings.
What version of PHP are we talking about?
First thing comes to mind: did you add it to autoload ?
I would use the __constructor methode as initiator routine of the class.
public static function calculate() {
return $this - > marks1 + $this - > marks2 + $this - > getAdditionalmarks();
}
You can't operate on $this from a static context. Make this method non-static, or adjust the other variables to be static, whichever suits your context.
Related
Consider this class arrangement - and in particular the magic function __invoke:
class Barman {
public function __construct() {
// .. .constructor stuff - whatever
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function __invoke($barman_id) {
echo "I have been invoked";
return $this->arr_barmen[$barman_id];
}
public function aBarFunc($param) {
return "yes it worked ," .$param;
}
}
class Foo {
public $myBar;
public function __construct() {
$this->myBar = new Bar();
}
}
I want to write syntax like this
$company = new Foo();
$company->myBar('john')->makeDrink();
Preferred result:
"vodka martini, shaken"
Actual result:
"Call to undefined method Foo::myBar()"
Invoking myBar() with the magic method should return a barman Object upon which you can call any of the barman's public methods
But now consider this (which does work)
$company = new Foo();
$myBar = $company->myBar;
$drink = $myBar('john')->makeDrink();
echo $drink;
// Result:
// I have been invoked
// vodka martini, shaken
So what's going on? I don't like that workaround - it's not sleek.
I need it to work this way:
$company->myBar('john')->makeDrink();
Please help? :-)
I believe you can just add braces around it:
$company = new Foo();
$drink = ($company->myBar)('john')->makeDrink();
echo $drink; // vodka martini, shaken
This is being caused by an ambiguity in the call you're trying to make:
$company->myBar('john')->makeDrink();
Because myBar is a property, the PHP interpreter isn't expecting it to be callable. It is parsing it as an attempt to call a method called myBar() which doesn't exist, and is thus throwing the error.
The direct way to resolve this is to clarify the ambiguity for the interpreter. You do this by adding curly braces around the property, as follows:
$company->{myBar}('john')->makeDrink();
The code is now explicit that myBar is a property and should be accessed as such, but that it contains a value that is callable and that you wish to make that call.
This whole topic is complicated (slightly) by the fact that PHP 5.x and PHP 7.x behave differently with regard to how they default to handling these kinds of ambiguity. PHP 7 changed the defaults in order to correct some internal inconsistencies within the language. The result is that in situations like this where you have an ambiguity, if you want your code to work across both PHP 5.x and 7.x, you should always use the braces to explicitly define how you want it to work, regardless of whether your code works for you without them.
There is some documentation about this change in the PHP 7.0 upgrade notes, although the examples given don't cover your exact situation.
To attain chaining you have to return the Barman object in invoke.
class Barman {
public function __construct() {
// .. .constructor stuff - whatever
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function __invoke($barman_id) {
echo "I have been invoked";
return $this->arr_barmen[$barman_id] = new Barman();
}
public function aBarFunc($param) {
return "yes it worked ," . $param;
}
}
class Foo {
public $myBar;
public function __construct() {
$this->myBar = new Bar();
}
// create a function with variable name to invoke the object
public function myBar($name) {
$mybar = $this->myBar;
return $mybar($name);
}
}
Thank you for the responses. I devised a cute workaround as follows:
class Barman {
public function __construct() {
}
public function makeDrink() {
return "vodka martini, shaken";
}
}
class Bar {
private $arr_barmen = array();
public function __construct() {
$this->arr_barmen['john'] = new Barman();
}
public function getBarman($barman_id) {
return $this->arr_barmen[$barman_id];
}
public function __invoke($barman_id) {
echo "I have been invoked \n";
return $this->arr_barmen[$barman_id];
}
}
class Foo {
private $_myBar;
public function __construct() {
$this->_myBar = new Bar();
}
// The fix
public function myBar($barman_id) {
return $this->_myBar->getBarman($barman_id);
}
}
Usage:
$company = new Foo();
$drink = $company->myBar('john')->makeDrink();
echo $drink; // vodka martini, shaken
How it works?
Foo->myBar becomes private (Foo->$_myBar);
we create a public function with the name myBar inside Foo;
we create a "getBarman" fuction inside Bar which is called from Foo->myBar('john')
A few more steps - and now there's no ambiguity - Foo->myBar() IS always a function.
Cheers
M
I am trying to reduce code on an API class, what I am looking to do is to make sure a method exists before calling the method inside of the class.
Will be passing a method as a variable need to see if that method exists inside of the class then run the method.
Sample code below:
<?php
class Test {
private $data;
private $obj;
public function __contruct($action,$postArray)
{
$this->data = $postArray;
if (method_exists($this->obj, $action)) {
//call method here
//This is where it fails
$this->$action;
}else{
die('Method does not exist');
}
}
public function methodExists(){
echo '<pre>';
print_r($this->data);
echo '</pre>';
}
}
//should run the method in the class
$test = new Test('methodExists',array('item'=>1,'blah'=>'agadgagadg'));
//should die()
$test2 = new Test('methodNotExists',array('item'=>1,'blah'=>'agadgagadg'));
?>
Is this even possible?
You just need to change $this->$action to $this->{$action}(); and it should work.
More in depth answer here including call_user_func
You have a typo in the name of your constructor function and second, when calling the method_exists() function you should be passing $this as the first parameter, not $this->obj:
public function __construct($action,$postArray)
{
$this->data = $postArray;
if (method_exists($this, $action)) {
$this->{$action}();
}else{
die('Method does not exist');
}
}
I have a class and I am including the players.php file inside it.
class My_Class {
private $player_types;
public function __construct() {
$this->player_types = 'classic';
require_once('players.php');
}
public function getPlayerTypes() {
return $this->player_types;
}
}
$mc = new My_Class();
How can I call getPlayerTypes function from players.php?
Also if its better to maybe use static method?
Just write :
$result = $this->getPlayerTypes();
echo $result;
inside the players.php. Definitely this will work.
Since the getPlayerTypes() is a method defined in the class My_Class, if you want to call that method from players.php you should instantiate a new My_Class object in that file and call the getPlayerTypes() there.
//player.php
$mc = new My_Class();
$playerTypes = $mc->getPlayerTypes();
echo $playerTypes
and remove that
require_once('players.php');
from your class :)
Since you are instantiating the class with the variable $mc, you'd call the function using
$mc->getPlayerTypes();
Or you can assign a variable to the result,
$result = $mc->getPlayerTypes();
echo $result;
The following is my simplified code
<?php
$database = new db();
$file = new file();
$input = new input();
$output = new output();
$data = "SELECT * FROM table;";
$input->page($data);
class db {
public function queryExecute($var) {
$var = $this->queryEncode($var);
$var = $this->querySubmit($var);
return $var;
}
public function queryEncode($var) {
// Do somthing
return $var;
}
public function querySubmit($var) {
// Do somthing
return $var;
}
}
The issue is when I add this to the code:
class input {
public function page($data) {
// Do something
$pageQuery = db::queryExecute($data);
}
}
With this, there are two things I have to do. First, I have to hide the errors for the db::queryExecute($data); code if the server is set to strict. And now for the second problem. I can't seem to use this line of code (which is the only way I have yet found possible for referencing other classes besides using Abstract) if the class that is being referenced is referencing yet another class but this time within it's own class.
For better explanation, the procedure is as follows:
Grab the $data variable and send it to the $input->page() function ( $input->page($data) ).
Referencing the db class, the $input->page() function sends the information onto the $database->queryExecute() function by means of the db::queryExecute() format ( db::queryExecute($data) ).
But because we are using the ::, when $database->queryExecute() references $database->queryEncode() and $database->querySubmit() using $this-> operator ( $this->queryEncode() and $this->querySubmit() ), $this-> currently belongs to $input-> and not $database->.
So what's the solution... Reference the other class differently (instead of ::)? Use a $_GLOBAL variable when I define my classes? Use something other than $this->? Configure all of the classes to use ABSTRACT/EXTENDS (or INTERFACE)?
The following error outputted refers to $var = $this->queryEncode($var);:
Fatal error: Call to undefined method input::querySubmit() in C:\[...]\global.php on line 12
Do not make static call to not static function. Pass $db instance to page, or provide global access to the database (via global registry, singleton or other method). But best, pass the dependency - the database instance, to the method.
<?php
$database = new db();
$file = new file();
$input = new input($database);
$output = new output();
$data = "SELECT * FROM table;";
$input->page($data);
class db {
public function queryExecute($var) {
$var = $this->queryEncode($var);
$var = $this->querySubmit($var);
return $var;
}
public function queryEncode($var) {
// Do somthing
return $var;
}
public function querySubmit($var) {
// Do somthing
return $var;
}
}
class input {
protected $_database;
public function __construct($database) {
$this->_database = $database;
}
public function page($data) {
// Do something
$pageQuery = $this->_database->queryExecute($data);
}
}
You can only use the double-colon operator on static, constant, or overridden properties or methods of a class. See the documentation on this. Use -> instead.
I want to access private methods and variables from outside the classes in very rare specific cases.
I've seen that this is not be possible although introspection is used.
The specific case is the next one:
I would like to have something like this:
class Console
{
final public static function run() {
while (TRUE != FALSE) {
echo "\n> ";
$command = trim(fgets(STDIN));
switch ($command) {
case 'exit':
case 'q':
case 'quit':
echo "OK+\n";
return;
default:
ob_start();
eval($command);
$out = ob_get_contents();
ob_end_clean();
print("Command: $command");
print("Output:\n$out");
break;
}
}
}
}
This method should be able to be injected in the code like this:
Class Demo
{
private $a;
final public function myMethod()
{
// some code
Console::run();
// some other code
}
final public function myPublicMethod()
{
return "I can run through eval()";
}
private function myPrivateMethod()
{
return "I cannot run through eval()";
}
}
(this is just one simplification. the real one goes through a socket, and implement a bunch of more things...)
So...
If you instantiate the class Demo and you call $demo->myMethod(), you'll get a console: that console can access the first method writing a command like:
> $this->myPublicMethod();
But you cannot run successfully the second one:
> $this->myPrivateMethod();
Do any of you have any idea, or if there is any library for PHP that allows you to do this?
Thanks a lot!
Just make the method public. But if you want to get tricky you can try this (PHP 5.3):
class LockedGate
{
private function open()
{
return 'how did you get in here?!!';
}
}
$object = new LockedGate();
$reflector = new ReflectionObject($object);
$method = $reflector->getMethod('open');
$method->setAccessible(true);
echo $method->invoke($object);
EDIT:
Updated to include examples of private function calls with parameters.
As of PHP 5.4, you can use the predefined Closure class to bind a method/property of a class to a delta functions that has access even to private members.
The Closure class
For example we have a class with a private variable and we want to access it outside the class:
class Foo {
private $bar = "Foo::Bar";
private function add_ab($a, $b) {
return $a + $b;
}
}
PHP 5.4+
$foo = new Foo;
// Single variable example
$getFooBarCallback = function() {
return $this->bar;
};
$getFooBar = $getFooBarCallback->bindTo($foo, 'Foo');
echo $getFooBar(); // Prints Foo::Bar
// Function call with parameters example
$getFooAddABCallback = function() {
// As of PHP 5.6 we can use $this->fn(...func_get_args()) instead of call_user_func_array
return call_user_func_array(array($this, 'add_ab'), func_get_args());
};
$getFooAddAB = $getFooAddABCallback->bindTo($foo, 'Foo');
echo $getFooAddAB(33, 6); // Prints 39
As of PHP 7, you can use the new Closure::call method, to bind any method/property of an obect to a callback function, even for private members:
PHP 7+
$foo = new Foo;
// Single variable example
$getFooBar = function() {
return $this->bar;
};
echo $getFooBar->call($foo); // Prints Foo::Bar
// Function call with parameters example
$getFooAddAB = function() {
return $this->add_ab(...func_get_args());
};
echo $getFooAddAB->call($foo, 33, 6); // Prints 39
The first question you should ask is, if you need to access it from outside the class, why did you declare it private? If it's not your code, the originator probably had a good reason to declare it private, and accessing it directly is a very bad (and largely unmaintainable) practice.
EDIT: As Adam V. points out in the comments, you need to make the private method accessible before invoking it. Code sample updated to include this. I haven't tested it, though - just adding here to keep the answer updated.
That having been said, you can use Reflection to accomplish this. Instantiate ReflectionClass, call getMethod for the method you want to invoke, and then call invoke on the returned ReflectionMethod.
A code sample (though I haven't tested it, so there may be errors) might look like
$demo = new Demo();
$reflection_class = new ReflectionClass("Demo");
$reflection_method = $reflection_class->getMethod("myPrivateMethod");
$reflection_method->setAccessible(true);
$result = $reflection_method->invoke($demo, NULL);
Here's a variation of the other answers that can be used to make such calls one line:
public function callPrivateMethod($object, $methodName)
{
$reflectionClass = new \ReflectionClass($object);
$reflectionMethod = $reflectionClass->getMethod($methodName);
$reflectionMethod->setAccessible(true);
$params = array_slice(func_get_args(), 2); //get all the parameters after $methodName
return $reflectionMethod->invokeArgs($object, $params);
}
I have these problems too sometimes, however I get around it through my coding standards. Private or protected functions are denoted with a prefix underscore ie
private function _myPrivateMethod()
Then i simply make the function public.
public function _myPrivateMethod()
So although the function is public the naming convention gives the notification that whilst public is is private and shouldn't really be used.
If you are able to added a method in the class where the method is defined, you can add method which uses the call_user_method() internally. This works also with PHP 5.2.x
<?php
class SomeClass {
public function callprivate($methodName) {
call_user_method(array($this, $methodName));
}
private function somePrivateMethod() {
echo 'test';
}
}
$object = new SomeClass();
$object->callprivate('somePrivateMethod');
Answer is put public to the method. Whatever trick you are going to do it wouldn't be understandable to fellow developers. For example they do not know that at some other code this function has been accessed as public by looking at the Demo class.
One more thing. that console can access the first method writing a command like:. How can this even be possible? Console can not access demo class functions by using $this.
I guess the reflectionClass is the only alternative if you really want to execute some private methods. Anyhow, if you just need read access to privat or protected properties, you could use this code:
<?php
class Demo
{
private $foo = "bar";
}
$demo = new Demo();
// Will return an object with public, private and protected properties in public scope.
$properties = json_decode(preg_replace('/\\\\u([0-9a-f]{4})|'.get_class($demo).'/i', '', json_encode((array) $demo)));
?>
<?php
$request="email";
$data=[1,2,3,4,5];
$name=new Update($request,$data);
class Update{
private $request;
private $data;
function __construct($request,$data){
$this->request=$request;
$this->data=$data;
if($this->request=='email'){
$this->update_email();
}
else{
echo "Can't do anything";
}
}
private function update_email(){
echo $this->request;
echo '\n';
foreach($this->data as $x){
echo $x."\n";
}
}
}
?>