Here is the code:
class Crud {
public static function get($id);
echo "select * from ".self::$table." where id=$id";// here is the problem
}
class Player extends Crud {
public static $table="user"
}
Player::get(1);
I could use Player::$table, but Crud will be inherited in many classes.
Any idea ?
To refer to static members in PHP there are two keywords :
self for "static" binding (the class where it is used)
static for "dynamic"/late static binding (the "leaf" class)
In your case you want to use static::$table
You want to use static:
<?php
class Crud {
public static $table="crud";
public static function test() {
print "Self: ".self::$table."\n";
print "Static: ".static::$table."\n";
}
}
class Player extends Crud {
public static $table="user";
}
Player::test();
$ php x.php
Self: crud
Static: user
Some explanation from the documentation:
http://php.net/manual/en/language.oop5.late-static-bindings.php
"Late binding" comes from the fact that static:: will not be resolved using the class where the method is defined but it will rather be computed using runtime information. It was also called a "static binding" as it can be used for (but is not limited to) static method calls.
Related
Let's say that I have some functions in my abstract parent class. I want these to only be accessible by the children classes, so I mark the functions protected (non-static).
abstract class ParentClass
{
protected function myFunction()
{
//implementation
}
}
My problem is the following: I have a few children classes and most of them use the aforementioned protected functions. I want to create a child class though, which allows the programmer to use those functions directly.
So basically:
class ChildClass extends ParentClass
{
public static function myAwesomeFunction()
{
parent::myFunction();
}
}
This is what I want to do. I want the user to be able to call the function (can be with the same name - myFunction in the child class) in a static way from the child class, but not from the parent class (that's why I don't want to make the function public, plus since I want it to be static, marking the class abstract doesn't help with this).
To be able to call
ChildClass::myAwesomeFunction();
but not to be able to do
ParentClass:myFunction();
Is there a trick to achieve this? If not, what is the best practice to do this? Is the only way really to enumerate all the functions I want and have them call the parent's method (like I have in my example)?
You could define the abstract to be protected static and then use the self keyword in the child:
abstract class A
{
protected static function _foo() {
echo "foo\n";
}
}
class B extends A
{
public static function foo() {
self::_foo();
}
}
A::_foo(); // fatal
B::foo(); // works
Given that, I'm not really crazy about this technique, and I would generally recommend avoiding static methods -- then it simply becomes a matter of defining the abstract protected and letting the child inherit it.
$this is use for current class and view is method but what is load. Is this a property?
Is this example correct?
class super{
public $property;
public function superf1()
{
echo "hello";
}
public function col()
{
$this->superf1();
}
$this->property->super1();
}
Yes, load is a property.
Think of it like this:
class Loader {
public function view() {
//code...
}
}
class MyClass {
private $load;
public __constructor() {
$this->load = new Loader();
}
public someMethod() {
$this->load->view();
}
}
This syntax is called chaining.
Your controller inherits CI_Controller. So, if you look in application/system/core/Controller.php you'll find something interesting : $this->load =& load_class('Loader', 'core'); (l.50 with CI2). So, $this->load refer to the file application/system/core/Loader.php which have a function public function view (l.418 with CI2)
In the context of a class that extends CI_Controller (in other words: a controller) the symbol $this is the Codeigniter "super object". Which is, more or less, the central object for CI sites and contains (among other things) a list of loaded classes. load is one of the classes you'll always find there because it is automatically loaded by the CI system.
Technically, the class creates objects of the type CI_Loader. view() is just one of the many methods in the load class. Other commonly used class methods are model(), library(), config(), helper(), and database(). There are others.
So, in short, load is a class used to load other resources.
load is a class belongs to the loader class
codeigniter official documentation
view, model and others are methods
In PHP 8.1
use return("viewname", $data)
If I give the same name to a function in the Model of Codeigniter, that function gets called automatically when I load the model.
//controller
$this->load->model('my_model');
//model
class My_model extends CI_model {
function my_model {
}
}
In this case I don't have to call my model function like this
$this->my_model->my_model();
because loading the model calls the function as well.
Can somebody explain this behaviour? I haven't found anything in docs regarding this.
This is a common concept in Object-Orientated programming. The function is acting as a Constructor. The constructor is called when an instance of the object is created.
In PHP using the __construct() method is the advised way to declare a constructor for the class. However, in PHP 4, a constructor was declared using the class name, so:
For backwards compatibility, if PHP 5 cannot find a __construct()
function for a given class, and the class did not inherit one from a
parent class, it will search for the old-style constructor function,
by the name of the class.
In CodeIgniter, a model is a class. As you don't have a __construct() method in your class, PHP is treating your my_model function as the constructor for the class (as it is the same as the class name).
You may want to the following method to your model. This will stop my_model being treating as a constructor.
function __construct()
{
// Call the Model constructor
parent::__construct();
}
I'd personally avoid calling a method the same name as the class in PHP, as it can lead to this confusion! PHP's docs have some useful information on constructors.
The following code will have PHP unhappy that customMethod() is private. Why is this the case? Is visibility determined by where something is declared rather than defined?
If I wanted to make customMethod only visible to boilerplate code in the Template class and prevent it from being overriden, would I just alternatively make it protected and final?
Template.php:
abstract class Template() {
abstract private function customMethod();
public function commonMethod() {
$this->customMethod();
}
}
CustomA.php:
class CustomA extends Template {
private function customMethod() {
blah...
}
}
Main.php
...
$object = new CustomA();
$object->commonMethod();
..
Abstract methods cannot be private, because by definition they must be implemented by a derived class. If you don't want it to be public, it needs to be protected, which means that it can be seen by derived classes, but nobody else.
The PHP manual on abstract classes shows you examples of using protected in this way.
If you fear that customMethod will be called outside of the CustomA class you can make the CustomA class final.
abstract class Template{
abstract protected function customMethod();
public function commonMethod() {
$this->customMethod();
}
}
final class CustomA extends Template {
protected function customMethod() {
}
}
Abstract methods are public or protected. This is a must.
Nothing in PHP that is private in a child class is visible to a parent class. Nothing that is private in a parent class is visible to a child class.
Remember, visibility must flow between the child class up to the parent class when using abstract methods in PHP. Using the visibility private in this scenario with PHP would completely encapsulate CustomA::customMethod inside of CustomA. Your only options are public or protected visibility.
Since you cannot make an instance of the abstract class Template, privacy from client-code is maintained. If you use the final keyword to prevent future classes from extending CustomA, you have a solution. However, if you must extend CustomA, you will have to live with how PHP operates for the time being.
I've set up an abstract parent class, and a concrete class which extends it. Why can the parent class not call the abstract function?
//foo.php
<?php
abstract class AbstractFoo{
abstract public static function foo();
public static function getFoo(){
return self::foo();//line 5
}
}
class ConcreteFoo extends AbstractFoo{
public static function foo(){
return "bar";
}
}
echo ConcreteFoo::getFoo();
?>
Error:
Fatal error: Cannot call abstract method AbstractFoo::foo() in foo.php on line 5
This is a correct implementation; you should use static, not self, in order to use late static bindings:
abstract class AbstractFoo{
public static function foo() {
throw new RuntimeException("Unimplemented");
}
public static function getFoo(){
return static::foo();
}
}
class ConcreteFoo extends AbstractFoo{
public static function foo(){
return "bar";
}
}
echo ConcreteFoo::getFoo();
gives the expected "bar".
Note that this is not really polymorphism. The static keywork is just resolved into the class from which the static method was called. If you declare an abstract static method, you will receive a strict warning. PHP just copies all static methods from the parent (super) class if they do not exist in the child (sub) class.
You notice that word self?
That is pointing to AbstractClass. Thus it is calling AbstractClass::foo(), not ConcreteClass::foo();
I believe PHP 5.3 will provide late static bindings, but if you are not on that version, self will not refer to an extended class, but the class that the function is located in.
See: http://us.php.net/manual/en/function.get-called-class.php
It's a rule that abstract and static keywords can not be use on a method at the same time.
A method with an abstract keyword means that sub-class must implement it. Adding static to a method of a class allows us to use the method without instantiating it.
So that is why the error occurs.