i've one stupid question.
I keep trying to write my framework, but ... i miss something.
I have one base class Base.class.php, with some functions.
When, i write another class SubBase.class.php, who extends Base, i trying to set one variable , who must use in Base class, in one static function (maybe).
Something like that
class Base {
public $vars;
public function GetA() {
return $this->vars;
}
}
public SubBase extends Base {
public function __construct() {
$this->vars = array();
}
}
But, i missing something ...
In role, my SubBase is subpage from my web, Base is printHTML class. I trying to set a title to my web, with my Base class, who set $this->vars in my SubBase class o.O
Please, tell me if i'm wrong, and let me know how to write this.
I wonna just write
<title> <?php echo Base::GetTitle(); ?> </title>
and show in.
Well, you should take a look at static properties and methods: http://php.net/manual/en/language.oop5.static.php
To accomplish what you want, you can try the following:
class Base {
//--------------------------------
// Declare static property
public static $title = '';
//--------------------------------
// Declare static method
public static function GetTitle() {
return self::$title;
}
}
public SubBase extends Base {
//--------------------------------
// Construct which overwrites
// Base::$title
public function __construct($newTitle){
self::$title = $newTitle;
}
}
//--------------------------------
// Instantiate your SubBase object
$subPage = new SubBase($newTitle = 'Welcome to my sub page');
//--------------------------------
// And in your HTML, use
<title> <?php echo SubBase::GetTitle(); ?> </title>
Note, that I used SubBase::GetTitle(); and not Base::GetTitle(); If you use Base::GetTitle(), you're output will be blank because you're using the value given at the Base Class. In my example, its:
public static $title = '';
However, when you instantiate your SubBase class, you provide a "$newTitle" parameter, which then overrides the blank value.
Ideally, this should work. Still, I recommend you learn more about the use of static properties and methods.
Hope this helps.
Related
I have a class base which has a property called load which is a object of the class load. The load class has a function called view that includes pages. Now I need to call,
This is similar to CodeIgniter's $this->load->view("test.php");
Load Class
class Load {
public function view($page){
//this function loads views to display
include($page);
}
public function model($class){
//loads model classes
}
public function library($class){
//loads libraries
}
}
Base Class
class Base {
function __construct(){
$this->load = new Load();
}
}
Index page
$base = new Base();
$base->load->view("test1.php");
this1.php
echo "testing1\n";
$this->load->view("test2.php");
test2.php
echo "testing2";
The output should be
testing1
testing2
What you really want I think is to follow a factory pattern. (At least, that's what you mean if you want the $view variable to actually contain an instance of the Load class)
Make the constructor protected, so that the only the class can create new instances, then in the base class add a static method, e.g. 'factory' which returns an instance of the desired class.
Then your code would look like
$view=Base::factory();
$view->view("test1.php");
NOTE: this answer was made before any edit made to the question. Please evaluate accordingly
You need to have the functions marked as public to allow them to be called from outside of the defining class (this is simplified of course)
Try the following:
class Load{
public function view($page){
include($page);
}
}
class Base{
public $load;
function __construct(){
$this->load = new Load();
}
}
(The uppercase class names are my own preference)
This should work, but it's not a good design from a clean OOP perspective, because the users of the Base class need to know how the Load class works. This is called "tight coupling" and should be avoided as much as possible.
I suggest to consider the following alternative:
class Load{
public function view($page){
include($page);
}
}
class Base{
private $load; //note the private modifier
function __construct(){
$this->load = new Load();
}
public function view($page){
$this->load->view($page);
}
}
This way I just need to know that Base has a method view($page) and i don't have to know anymore what Load does at all.
If in the future you want to change the Load class you can do it under the hood without the Base users ever noticing it, if you do it right:
Suppose you define a class:
class BetterLoad {
private function foo(){
//do something awesome
}
private function advancedView($page){
include($page);
$this->foo();
}
}
and you want to incorporate this inside Base instead of the old Load.
class Base{
private $adv_load; //note the private modifier
function __construct(){
$this->adv_load = new BetterLoad();
}
public function view($page){
$this->adv_load->advancedView($page);
}
}
That's it. You won't need to change anything else in your code. Just go on using the old $base_obj->view($page) and you're good to go, without even noticing the change.
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.
so I'm trying to work out an issue I'm having in designing PHP classes. I've created a base class, and assigned private variables. I have child classes extending this base class, which make reference and changes to these private variables through functions of the base class. Here's an example, keep in mind I'm still confused about the difference between private and protected methods/variables (let me know if I'm doing it wrong!):
base.class.php
<?php
class Base {
private $test;
public function __construct(){
require('sub.class.php');
$sub = new Sub;
echo($this->getTest());
}
public function getTest(){
return $this->test;
}
protected function setTest($value){
$this->test = $value;
}
}
?>
sub.class.php
<?php
class Sub extends Base {
public function __construct(){
parent::setTest('hello!');
}
}
?>
So I'd expect the result to be hello! printed on the screen - instead there is nothing. There could be a fundamental misunderstanding of classes on my part, or maybe I'm just doing something wrong. Any guidance is very much appreciated! Thanks.
EDIT:
Thank you to everyone who contributed an answer - I think, despite the excellent solutions, that child classes are actually not what I need - it seems delegate classes may be more useful at this point, as I don't really need to reference the Base functions from within the other classes.
Should be like this:
base.class.php:
class Base {
private $test;
public function __construct() {
echo $this->getTest();
}
public function getTest() {
return $this->test;
}
protected function setTest($value) {
$this->test = $value;
}
}
sub.class.php:
class Sub extends Base {
public function __construct() {
parent::setTest('hello!'); // Or, $this->setTest('hello!');
parent::__construct();
}
}
main code:
require 'base.class.php';
require 'sub.class.php';
$sub = new Sub; // Will print: hello!
How can I initialize class' base class by return value in construct? Let's say I have this as a base class:
class Base
{
public function Foo()
{
}
private $_var;
}
I also have this one static method from another class, which returns Base class:
class MyStaticClass
{
public static function Get()
{
return new Base();
}
}
and now I derive from base class it here:
class Derived extends Base
{
public function __construct()
{
// Here, how can I initialize Base class with
// object MyStaticClass returns? Something like
parent = MyStaticClass::Get(); // This doesn't obviously work..
}
}
Is there any solution / workaround to this?
Though it seems like an uncommon way of doing it, you probably mean this:
class Derived extends Base
{
public function __construct()
{
parent::__construct(MyStaticClass::Get());
}
}
I have not found a way to directly do that, but if you are willing to let go of class, you can accomplish this with javascript-style OOP. See my answer on https://stackoverflow.com/a/10468793/1369091
Hi i have a little collection of classes some of which should be globally accessible.
I found something similar in Zend_Registry, but reading its code i cant understand how a call to a static function could return an initialized instance of a class...
i need to do something like:
<?php
//index.php
$obj = new myUsefulObject();
$obj->loadCfg("myFile.xml");
$req = new HTTPRequest();
$req->filter("blablabla");
myappp::registerClass("object",$obj);
myappp::registerClass("request",$req);
$c = new Controller();
$c->execute();
?>
Here i have filtered the Request object and i want the controller to be able to reach that already filtered request.
<?php
class Controller
{
function __construct()
{
$this->request = Application::getResource("request");//This must be the filtered var =(
}
}
?>
I don't know how to implement that Application::getResource(), the only thing i know is that it must be a static method because it can't be related to a specific instance.
Aside from static methods, PHP also has static properties: properties that are local to the class. This can be used to implement singletons, or indeed a Registry:
class Registry {
private static $_registry;
public static function registerResource($key, $object)
{
self::$_registry[$key] = $object;
}
public static function getResource($key) {
if(!isset(self::$_registry[$key]))
throw InvalidArgumentException("Key $key is not available in the registry");
return self::$_registry[$key];
}
}
1: You can acess global variables with the global keyword:
$myVar = new SomethingProvider();
class MyClass {
public function __construct() {
global $myVar;
$myVar->doSomething();
}
}
2: You can do the same using the $GLOBALS super-global:
$myVar = new SomethingProvider();
class MyClass {
public function __construct() {
$GLOBALS['myVar']->doSomething();
}
}
3: You can define a singleton class (the wikipedia has a nice example, too).
4: You could add globals as public static members (or private static members with public getters/setters) to a class:
class Constants {
const NUM_RETIES = 3;
}
if ($tries > Constants::NUM_RETRIES) {
# User failed password check too often.
}
class Globals {
public static $currentUser;
}
Globals::$currentUser = new User($userId);
I wouldn't recommend the first two methods, overwriting the values of these global variables unintentionally is too easy.
Seems to me like you might need some form of Singleton design pattern;
Check this out!
Hope it helps!