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.
Related
I am interested in how this works:
<?php
$Query = $mysqli->query("select * from table");
$Query->fetch_array(); // <== How to make $Query a class/method like this?
?>
How do you assign a method to a variable and then have that variable be able to call another method like the $mysqli and $Query example above?
One way to achieve what you are (I think) referring to, is by returning an object. It goes against the principle of dependency injection, but it's one way to do it.
class MyClassA
{
public function myFunction()
{
return new MyClassB();
}
}
class MyClassB
{
public function execute()
{
return true;
}
}
// Start use
$class = new MyClassA();
// Assign variable to function which returns object
$newObj = $class->myFunction();
// Will write "1" because now $newObj is MyClassB()
echo $newObj->execute();
Another way is to return $this from the first method. The usage of the above object would work identical in this instance, however you also allow another principle known as method chaining:
class MyClassA
{
public function myFunction()
{
return $this;
}
public function execute()
{
return true;
}
}
// Same as above works
$class = new MyClassA();
$sameObj = $class->myFunction();
echo $sameObj->execute();
// Allowing for Method Chain
$class = new MyClassA();
// Allowing for chaining
echo $class->myFunction()->execute();
You have to instantiate your class and call it's function with ->
$class = new MyClass(); // Instantiate class
$class->myFunction(); // Use it's function
PHP manual example of creating a class:
http://php.net/manual/en/language.oop5.basic.php
I'm trying to do something like this:
function doSomething($param, Class) {
Class::someFunction();
}
$someVar = doSomething($param, Class);
Is it possible?
To explain better what I'm trying to do. I have a helper function in Laravel to generate unique slugs, so I have to query different tables depending on where the slug is going to be saved.
Actual code I'm trying to write:
$newcat->slug = $helper->uniqueSlug($appname, Apk);
public function uniqueSlug($str, Apk)
{
$slug = Str::slug($str);
$count = Apk::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();
return $count ? "{$slug}-{$count}" : $slug;
}
Thanks!
You can use the magic ::class constant:
public function uniqueSlug($str, $model)
{
$slug = Str::slug($str);
$count = $model::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();
return $count ? "{$slug}-{$count}" : $slug;
}
$newcat->slug = $helper->uniqueSlug($appname, Apk::class);
In PHP, classes (or class names) are handled as strings. Since PHP 5.5, you can use YourClass::class to get a fully qualified class name.
If you want to get it in an earlier version of php, you can (if you have already an object of the calss) either do the following:
<?php
$obj = new YourClass();
// some code
$clazz = get_class($obj);
?>
or, you can implement a static method in your class, like this:
<?php
class YourClass {
// some code
public static function getClassName() {
return get_called_class();
}
?>
If you want to pass a class to a function, you can do it like this:
<?php
function do_somthing($arg1, $clazz) {
$clazz::someStaticMethod($arg1);
}
?>
or
<?php
function do_somthing($arg1, $clazz) {
call_user_func(array($clazz, 'someStaticMethod')), $arg1);
}
?>
If you need to call a non-static method of that class, you need to instanciate it:
<?php
function do_somthing($arg1, $clazz) {
$obj = new $clazz();
$obj->someNonStaticMethod();
}
?>
Note: You can use PHP type hinting with passed class names:
<?php
function do_somthing($arg1, MyInterface $clazz) {
$obj = new $clazz();
$obj->someInterfaceMethod();
}
?>
I think you can.
Send the class name as string parameter then use it like below.
$classtr = "yourparam";// param comes from the function call.
$obj = new $classtr;
$obj->method();
Send the class name as string parameter you need use the namespace. For example:
function defineClass()
{
$class = "App\MyClass"; // mention the namespace too
}
function reciveClass($class)
{
$class:: // what do you need,
}
How can I call following Class method or function?
Let say I have this params get from url:
$var = filter($_GET['params']);
Class:
class Functions{
public function filter($data){
$data = trim(htmlentities(strip_tags($data)));
if(get_magic_quotes_gpc())
$data = stripslashes($data);
$data = mysql_real_escape_string($data);
return $data;
}
}
thanks.
To answer your question, the current method would be to create the object then call the method:
$functions = new Functions();
$var = $functions->filter($_GET['params']);
Another way would be to make the method static since the class has no private data to rely on:
public static function filter($data){
This can then be called like so:
$var = Functions::filter($_GET['params']);
Lastly, you do not need a class and can just have a file of functions which you include. So you remove the class Functions and the public in the method. This can then be called like you tried:
$var = filter($_GET['params']);
Within the class you can call function by using :
$this->filter();
Outside of the class
you have to create an object of a class
ex: $obj = new Functions();
$obj->filter($param);
for more about OOPs in php
this example:
class test {
public function newTest(){
$this->bigTest();// we don't need to create an object we can call simply using $this
$this->smallTest();
}
private function bigTest(){
//Big Test Here
}
private function smallTest(){
//Small Test Here
}
public function scoreTest(){
//Scoring code here;
}
}
$testObject = new test();
$testObject->newTest();
$testObject->scoreTest();
hope it will help!
Create object for the class and call, if you want to call it from other pages.
$obj = new Functions();
$var = $obj->filter($_GET['params']);
Or inside the same class instances [ methods ], try this.
$var = $this->filter($_GET['params']);
$f = new Functions;
$var = $f->filter($_GET['params']);
Have a look at the PHP manual section on Object Oriented programming
As th function is not using $this at all, you can add a static keyword just after public and then call
Functions::filter($_GET['params']);
Avoiding the creation of an object just for one method call
You need to create Object for the class.
$obj = new Functions();
$var = $obj->filter($_GET['params']);
This way:
$instance = new Functions(); // create an instance (object) of functions class
$instance->filter($data); // now call it
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";
}
}
}
?>
Does anyone know how to reset the instance variables via a class method. Something like this:
class someClass
{
var $var1 = '';
var $var2 = TRUE;
function someMethod()
{
[...]
// this method will alter the class variables
}
function reset()
{
// is it possible to reset all class variables from here?
}
}
$test = new someClass();
$test->someMethod();
echo $test->var1;
$test->reset();
$test->someMethod();
I know I could simply do $test2 = new SomeClass() BUT I am particularly looking for a way to reset the instance (and its variables) via a method.
Is that possible at all???
You can use reflection to achieve this, for instance using get_class_vars:
foreach (get_class_vars(get_class($this)) as $name => $default)
$this -> $name = $default;
This is not entirely robust, it breaks on non-public variables (which get_class_vars does not read) and it will not touch base class variables.
Yes, you could write reset() like:
function reset()
{
$this->var1 = array();
$this->var2 = TRUE;
}
You want to be careful because calling new someClass() will get you an entirely new instance of the class completely unrelated to the original.
this could be easy done;
public function reset()
{
unset($this);
}
Sure, the method itself could assign explicit values to the properties.
public function reset()
{
$this->someString = "original";
$this->someInteger = 0;
}
$this->SetInitialState() from Constructor
Just as another idea, you could have a method that sets the default values itself, and is called from within the constructor. You could then call it at any point later as well.
<?php
class MyClass {
private $var;
function __construct() { $this->setInitialState(); }
function setInitialState() { $this->var = "Hello World"; }
function changeVar($val) { $this->var = $val; }
function showVar() { print $this->var; }
}
$myObj = new MyClass();
$myObj->showVar(); // Show default value
$myObj->changeVar("New Value"); // Changes value
$myObj->showVar(); // Shows new value
$myObj->setInitialState(); // Restores default value
$myObj->showVar(); // Shows restored value
?>