PHP make class propery inheritable - php

i have 2 classes A and B that extends A. A has a public property and i want that on the instances of B that property can't be accessible. I try to explain better:
class A
{
public $prop;
}
class B extends A
{
...
}
$instance=new B;
$instance->prop; //This must throw an error like "Undefined property prop"
I tried with the final keyword but it's only available for methods not for properties. I tried also by setting the same property as private on B but PHP does not allow to change the access level from public to private or protected.
Maybe there's a simple solution to this problem but i can't find it so do you know a way to do this?

Simply change public $prop; to private $prop; by making $prop public you are making it accessible by every possible way, but making it private will make it accessible within a class only

Use magic methods
class A {
protected $_prop;
public function __get($key) {
if ($key=='prop') {
return $this->_prop;
}
}
public function __set($key, $value) {
if ($key=='prop') {
return $this->_prop = $value;
}
}
}
class B extends A {
public function __get($key) {
}
public function __set($key, $value) {
}
// how you can use it
public function foo() {
echo $this->_prop;
}
}

Hmm. Tricky!
The only idea that comes to mind is making $prop private from the start, and using magic getter and setter functions to control access. You'd have to store the access information in a separate array and then either return the correct value, or throw a fatal error in the getter function.

Related

PHP - Achieve certain syntax with multiple classes

(PHP7) I have two classes but would like to access one class inside of another for example:
Syntax: Property::House()->getAddress();
class Property
{
protected $House;
function Property()
{
self::$House = new House();
}
public function House()
{
return self::$House;
}
}
class House
{
public function getAddress()
{
// code
}
}
does anyone know to accomplish this?, the syntax needs to be the same but the classes can change if needed
Firstly, your class setup is going to give you deprecation errors in PHP7. You'd be better off using the __construct() method in place of Property() if you're wanting to use non-static calls.
Secondly. Are you sure you don't want House to extend the Property class instead of being a property of the Property class?
Thirdly, assuming you're sure of what you're trying to achieve this should work...
<?php
class Property
{
static function House()
{
return new House();
}
}
class House
{
public function getAddress()
{
echo 'YAY!';
}
}
Property::House()->getAddress();

Correct way of using polyporphism in php?

I'm new to object oriented php. And if there are no functions in the method testing() in the HumanClass, should i declare them as abstract?
<?php
class HumanClass
{
private $legs;
private $hands;
public function __construct($legs, $hands)
{
$this->legs = $legs;
$this->hands = $hands;
}
public function testing()
{
}
}
class StudentClass extends HumanClass
{
private $books;
public function __construct($legs, $hands, $books)
{
parent::__construct($legs, $hands);
$this->books = $books;
}
public function testing()
{
echo "StudentClass called.";
}
}
function callClass(HumanClass $c)
{
$c->testing();
}
$example = new StudentClass(4, 2, 1);
callClass($a);
?>
Is it possible to have something like this?
echo $a->testing();
instead of having another method to call testing().
Given the code that you give, it's far from clear what the testing() function is supposed to do other than just exist for you to try things. The answer to that will also determine whether the versions in the baseclass should remain there as empty function.
There are other options, too, e.g. that the derived class first invokes the baseclass (extending), or that the baseclass doesn't contain an abstract or concrete such function but only the derived one does. Which to choose is up to the informed programmer to decide.

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.

Class returning object confusion

I've been asked to create a class that does some stuff, and then returns an object with read only properties.. Now I've created the class and I've got everything working 100%, however I'm confused when they say to 'return an object with read only properties'.
This is the outline of my php file which contains the class and some extra lines calling it etc:
class Book(){
protected $self = array();
function __construct{
//do processing and build the array
}
function getAttributes(){
return $this->self; //return the protected array (for reading)
}
}
$book = new Book();
print_r($book->getAttributes());
How can I return an object or something?
You are probably looking for the keyword final. Final means the object/method cannot be overridden.
Protected means that the object/method can only be accessed by the class who it belongs to.
Since self is a reserved keyword, you need to change that as well as your declarations. Rename $self an $this->self to $data and $this->data
self is a PHP reserved word. You have to renamed your variable.
What they're referring to is an object with private or protected properties which can only be accessed by setters/getters. The property will be read-only if you only define the getter method.
Something like:
Class Book {
protected $attribute;
protected $another_attribute;
public function get_attribute(){
return $this->attribute;
}
public function get_another_attribute() {
return $this->another_attribute;
}
public method get_this_book() {
return $this;
}
}
Now this is kind of s silly example because Book->get_this_book() would return itself. But this should give you an idea of how to set of getters on protected properties such that they are read only. And how to reutrn an object (in this case it returns itself).
read only property means you can access them but can not write them
class PropertyInaccessible {
//put your code here
protected $_data = array();
public function __get($name) {
if(isset ($this->_data[$name]))
return $this->_data[$name];
}
public function __set($name, $value) {
throw new Exception('Can not set property directly');
}
public function set($name, $value) {
$this->_data[$name] = $value;
}
}

Making a superclass object become a subclass object in PHP5

<?php
class A{
//many properties
protected $myProperty1;
protected $myProperty2;
protected $myProperty3;
public function __construct(){
$this->myProperty1='some value';
$this->myProperty2='some value';
$this->myProperty3='some value';
}
public function getProperty1(){
return $this->myProperty1;
}
public function getProperty2(){
return $this->myProperty2;
}
public function getProperty3(){
return $this->myProperty3;
}
//edited: I added some setters, meaning that the object returned from the functions may already have these properties altered
public function setProperty1($p){
$this->myProperty1=$p;
}
public function setProperty2($p){
$this->myProperty2=$p;
}
public function setProperty3($p){
$this->myProperty3=$p;
}
}
class B extends A{
private $myProperty4;
public function __construct(A $a){
$this=$a; //this line has error,it says $this cannot be re-assigned
$this->myProperty4='some value';
}
public function getProperty4(){
return $this->myProperty4;
}
}
//$a = new A();
$a = someClass::getAById(1234); //edited: $a is returned by a function (I cannot modify it)
$b= new B($a); //error
?>
I'd like to create a B's object by passing an A's object to B's constructor, as you can see, I cannot re-assign the $this variable. I am not allowed to modify class A, when there are many properties in A, it'd be tedious for me to do things like this in B's constructor:
public function __construct(A $a){
parent::__construct();
$this->myProperty1=$a->getProperty1();
$this->myProperty2=$a->getProperty2();
$this->myProperty3=$a->getProperty3();
$this->myProperty4='some value';
}
My question is that, how can I safely create an object of class B using an A's object with minimal amount of coding?
class A
{
public $property = 'Foobar';
}
class B extends A
{
public function __construct()
{
echo $this->property; // Foobar
}
}
Am I missing something? It sounds like you're trying to force OOP to do something it's not intended to do, or you're having trouble understanding inheritance.
Every public or protected method and property from class A is available in class B. Either by directly referencing it (as in my example) or by using the parent:: syntax.
EDIT
(Author clarified question)
If class A's properties are accessible, you could use something like the following to copy them down to class B
class B
{
public function __construct()
{
$a = new A(); // Or however A is instantiated
foreach(get_object_vars($a) as $key => $value)
{
$this->$key = $value;
}
}
}
Since B extends A, why not just create B to begin with? If you need to initialize some extra properties, you can over-ride the constructor like this:
class B extends A {
public function __construct(){
parent::__construct(); //calls A's constructor
$this->Bproperty='somevalue';
}
}
If that's not good enough, then you might want to look at Reflection.

Categories