Passing a variable into a protected function in PHP - php

I am working with a plugin where there is a protected function like so
<?php
class CustomUploadHandler extends UploadHandler {
protected function get_user_id() {
//If I manually enter a value here, the value passes along
return ('myvariable');
}
}
?>
Yet when I make a variable like
<?php $myvar = 'myvariable'; ?>
and try to insert it into the function like this
<?php
class CustomUploadHandler extends UploadHandler {
protected function get_user_id() {
//If I use a variable, the value is lost
return ($myvar);
}
}
?>
it completely fails...
I am unfamiliar with protected classes and also how return() works so any help would be greatly appreciated.
I have tried many lines of code such as
print $myvar; return $myvar; echo $myvar; with and without ()

Don't introduce global state via the global keyword. You'll be welcoming a world of pain down the line.
Instead, inject the dependency (the value, a user ID in this case) into the class when it's created, or with a setter.
class CustomUploadHandler extends UploadHandler
{
private $user_id;
protected function get_user_id()
{
return $this->user_id;
}
// setter injection; the value is
// passed via the method when called
// at any time
public function set_user_id($user_id)
{
$this->user_id = $user_id;
}
// constructor injection; the value is
// passed via the constructor when a new
// instance is created
public function __construct($user_id)
{
$this->set_user_id($user_id);
}
}
Then when you have an instance of this class:
// creates and sets $user_id = 42
$customUploadHandler = new CustomUploadHandler(42);
// sets $user_id = 77
$customUploadHandler->set_user_id(77);

Protected means that only the class itself, the parent class and the childs of the class where the function is defined can use the function. So it depends from where you call the function for it to work. return statements without brackets should be fine.

Related

Why isn't this function working?

I have declared the beats function and am trying to use it. What is the difference between var_dump(is_a($sci, 'Scissors')) and var_dump($roc->beats($sci))? When I run this code the first var_dump returns true and the second false. I want both to return true.
abstract Class Option
{
private $beats;
public function beats($opponentsChoice)
{
return is_a($opponentsChoice, $this->beats);
}
}
Class Rock extends Option
{
private $beats = 'Scissors';
}
Class Paper extends Option
{
private $beats = 'Rock';
}
Class Scissors extends Option
{
private $beats = 'Paper';
}
$roc = new Rock;
$pap = new Paper;
$sci = new Scissors;
var_dump(is_a($sci, 'Scissors'));
var_dump($roc->beats($sci));
The problem is your private variables.
private variables are scoped only to the class they are defined in. Option::$beats is a different variable than Rock::$beats.
If you change your variables to be protected instead, that will work, since all members of a class hierarchy will share protected variables (and methods).

Can I/How to... call a protected function outside of a class in PHP

I have a protected function that is defined within a certain class. I want to be able to call this protected function outside of the class within another function. Is this possible and if so how may I achieve it
class cExample{
protected function funExample(){
//functional code goes here
return $someVar
}//end of function
}//end of class
function outsideFunction(){
//Calls funExample();
}
Technically, it is possible to invoke private and protected methods using the reflection API. However, 99% of the time doing so is a really bad idea. If you can modify the class, then the correct solution is probably to just make the method public. After all, if you need to access it outside the class, that defeats the point of marking it protected.
Here's a quick reflection example, in case this is one of the very few situations where it's really necessary:
<?php
class foo {
protected function bar($param){
echo $param;
}
}
$r = new ReflectionMethod('foo', 'bar');
$r->setAccessible(true);
$r->invoke(new foo(), "Hello World");
That's the point of OOP - encapsulation:
Private
Only can be used inside the class. Not inherited by child classes.
Protected
Only can be used inside the class and child classes. Inherited by child classes.
Public
Can be used anywhere. Inherited by child classes.
If you still want to trigger that function outside, you can declare a public method that triggers your protected method:
protected function b(){
}
public function a(){
$this->b() ;
//etc
}
If the parent's method is protected, you can use an anonymous class:
class Foo {
protected function do_foo() {
return 'Foo!';
}
}
$bar = new class extends Foo {
public function do_foo() {
return parent::do_foo();
}
}
$bar->do_foo(); // "Foo!"
https://www.php.net/manual/en/language.oop5.anonymous.php
You can override this class with another where you make this public.
class cExample2 extends cExample {
public function funExample(){
return parent::funExample()
}
}
(note this won't work with private members)
But the idea of private and protected members is to NOT BE called from outside.
Another option (PHP 7.4)
<?php
class cExample {
protected function funExample(){
return 'it works!';
}
}
$example = new cExample();
$result = Closure::bind(
fn ($class) => $class->funExample(), null, get_class($example)
)($example);
echo $result; // it works!
If you want to share code between your classes you can use traits, but it depends how you want use your function/method.
Anyway
trait cTrait{
public function myFunction() {
$this->funExample();
}
}
class cExample{
use cTrait;
protected function funExample() {
//functional code goes here
return $someVar
}//end of function
}//end of class
$object = new cExample();
$object->myFunction();
This will work, but keep in mind that you don't know what your class is made of this way. If you change the trait then all of your classes which use it will be altered as well. It's also good practice to write an interface for every trait you use.
here i can give you one example like below
<?php
class dog {
public $Name;
private function getName() {
return $this->Name;
}
}
class poodle extends dog {
public function bark() {
print "'Woof', says " . $this->getName();
}
}
$poppy = new poodle;
$poppy->Name = "Poppy";
$poppy->bark();
?>
or one another way to use with latest php
In PHP you can do this using Reflections. To invoke protected or private methods use the setAccessible() method http://php.net/reflectionmethod.setaccessible (just set it to TRUE)
I am using Laravel. i was facing issue while access protected method outside of class.
$bookingPriceDetails = new class extends BookingController {
public function quotesPrice( $req , $selectedFranchise) {
return parent::quotesPrice($req , $selectedFranchise);
}
};
return $bookingPriceDetails->quotesPrice($request , selectedFranchisees());
here BookingController is Class name from which i want to get protected method. quotesPrice( $req , $selectedFranchise) is method that i want to access in different Class.

PHP Passing an object through a class?

After restructuring my entire class layout, I'm still having trouble using multiple class instances.
class User {
public $variable;
public function getUser() {
$this->variable = 'It works!';
return 'bob';
}
}
class Base {}
class One extends Base {
public function test() {
print_r($User->variable); // Want it to print 'It works!'
}
}
$User = new User();
$username = $User->getUser();
if($username === 'bob') {
$One = new One();
$One->test(); // prints "Notice: Undefined property: One::$variable
}
What the above code does: The class User gets the username. If the username is bob, it will create an object one and try to print the variable from class User. In my real code, User is extremely intricate and passing a bunch of things with __construct just isn't what I'm looking for.
I think the solution (which is why I titled this question as so) would be to create a new class User within class Base but I just can't wrap my head around having to create a whole new object and re-initiate everything just to get the username.
Inject your User instance:
class One {
private $user;
public function __construct(User $user) {
$this->user = $user;
}
public function test() {
print_r($this->user->variable);
}
}
$User = new User();
$One = new One($user);
$One->test();
This doesn't have any undue effects with regards to efficiency, as the instance is passed by reference as opposed to copied.
The class One does not know about the $User variable and therefore can not access it.
You could either pass the variable to the class in the constructor or set it after creation of an object of the class.
class One extends Base {
protected $user;
public function setUser(User $user) {
$this->user = $user;
}
public function One(User $user) {
$this->setUser($user);
}
public function test() {
print_r($this->user->variable);
}
}
Or (but please don't, it is bad practice) set the $User variable to global.
global $User

Wrap/Reuse/Clone a PHP object (code optimization)

Imagine two classes which share almost the same exact methods and properties, both extending a parent class, but the differences are minimal.
class fields {
public function __construct() {
global $id;
$this->id = $id++;
}
}
class input extends fields {
public function __construct() {
parent::__construct();
}
public function draw() {
echo '<input>';
}
}
class textarea extends fields {
public function __construct() {
parent::__construct();
}
public function draw() {
echo '<textarea>';
}
}
I'm thinking it would be more efficient to rewrite the textarea class in this psuedo-code fashion:
class textarea extends fields {
public function __construct() {
$this = new input(); // <<------
}
public function draw() {
echo '<textarea>';
}
}
Basically, I'm unsure how this would best be done so that the class acts like the class from the first example.
In essence, I would like to do the following using OOP, but be able to use the object as it can be in the first example above (be able to call the possibly overloaded methods, have different properties, etc.):
function a() {echo '123';}
function b() {a();}
I have just copied the entire class and modify a few lines, but I feel it is wasteful.
Final Answer
Thanks to those people, here is the combined answer with example calls:
abstract class fields {
private static $masterid = 0;
public function __construct() {
$this->id = self::$masterid++;
}
}
class input extends fields {
public $data;
public function __construct($new = '') {
parent::__construct();
if ($new) $this->data = $new;
else $this->data = 'Hello';
}
public function draw() {
echo '<input>'.$this->export().'</input>';
}
public function export() {
return 'ID '.$this->id.' = '.$this->data;
}
}
class textarea extends input {
public function __construct($new = '') {
parent::__construct($new);
}
public function draw() {
echo '<textarea>'.$this->export().'</textarea>';
}
}
$a = new textarea();
$a->draw();
$a = new textarea('World');
$a->draw();
$a = new input('!');
$a->draw();
//Outputs:
// <textarea>ID 0 = Hello</textarea>
// <textarea>ID 1 = World</textarea>
// <input>ID 2 = !</input>
Make the fields class an abstract class, and like Darren suggested, make the 'draw' method a function of the fields class.
Now heres the trick, you want the input class to extend fields, but override the draw method. This will allow you to customize the functionality of that method, and you can still call the parent variation from within it.
Finally, since the textarea class is going to have many similarities to the input class, make textarea extend input. Thereby inheriting the properties and methods of both fields and input.
Make the "fields" class have a draw method:
public function draw($msg) {
echo $msg;
}
Then in the textarea or input class put:
parent::draw("<input>");
This cuts down on the number of methods you have, and can call one method for both types of field.
Also in your "fields" class, change the id code to be like this:
public $id
public function __construct($id) {
$this->id = $id;
}
Then in the subclass:
parent::__construct(1); //Or whatever ID you want
The way you have it, ID is the same value every time you set it, which will result in every subclass of fields having the same id. This way each subclass will have a seperate ID.
Also because I'm nice, here's it all put together:
public class field {
$id;
public __construct($id) {
$this->id = $id;
}
public function draw($msg) {
echo $msg;
}
}
public class input extends field {
public __construct() {
parent::__construct(1);
parent::draw("<input>");
}
}
public class textarea extends field {
public __construct() {
parent::__construct(2);
parent::draw("<textarea>");
}
}
That's how I'd put it together from what you've said. I may have mistaken what you were asking for though. Can you tell I'm primarily a Java programmer from that?
It's not exactly clear what you want to do. For the example you've given, I think the structure is OK, but you should make a few changes, particularly with the constructor. I think the constructor should be abstract, with an abstract method draw().
abstract class fields {
// Use a static member to keep track of id's instead of making it global
private static $id = 0;
// Use an instance variable to keep track of a particular instance's id
private $myId;
public function __construct() {
// Increment the static ID & assign it to the instance id.
$this->myId = self::$id++;
}
// Provide a public getter, so that the ID can't be changed
// externally to this class
public function getId() {
return $this->myId;
}
public abstract draw(); // Make sure all sub classes implement a draw() method.
}
class input extends fields {
// Don't need to call the parent constructor if you're not adding anything
// else. It will be called automatically.
public function draw() {
echo '<input>';
}
}
class textarea extends fields {
public function draw() {
echo '<textarea>';
}
}

Global variable inside a constructor with PHP

This should be obvious, but I'm getting a bit confused about PHP variable scope.
I have a variable inside a Constructor, which I want to use later in a function in the same class. My current method is this:
<?php
class Log(){
function Log(){
$_ENV['access'] = true;
}
function test(){
$access = $ENV['access'];
}
}
?>
Is there a better way to do this than abusing environment variables? Thanks.
You could use a class variable, which has a context of... a class :
(Example for PHP 5, of course ; I've re-written a few things so your code is more PHP5-compliant)
class Log {
// Declaration of the propery
protected $_myVar;
public function __construct() {
// The property is accessed via $this->nameOfTheProperty :
$this->_myVar = true;
}
public function test() {
// Once the property has been set in the constructor, it keeps its value for the whole object :
$access = $this->_myVar;
}
}
You should take a look at :
The "Classes and Objects" section of the PHP manual
And, for this specific question, the sub-section Properties
Globals are considered harmful. If this is an outside dependency, pass it through the constructor and save it inside a property for later use. If you need this to be set only during the call to test, you might want to consider making it an argument to that method.
You could use the global keyword:
class Log{
protected $access;
function Log(){
global $access;
$this->access = &$access;
}
}
But you really should be passing the variable in the constructor:
class Log{
protected $access;
function Log($access){
$this->access = &$access;
}
//...Then you have access to the access variable throughout the class:
function test(){
echo $this->access;
}
}

Categories