I am very new to OOP and very rusty on PHP. I was wondering if this is a valid method to call a function from a class?
class newclass {
public function testfunc {
return '1';
}
}
Could I call it like this:
echo testfunc->newclass();
or like this:
echo newclass()::testfunc;
I always see it defined in examples like below and it seemed like extra code?:
$this = new newclass();
$this->testfunc();
echo $this;
Any help would be greatly appreciated as I'm just starting to wrap my head around this OOP thing. If I'm out to lunch maybe someone could suggest a link to a really good guide for a true beginner in classes/OOP. Thanks!
Both ways work and have their use cases.
Your first case is a regular function call using an instance of a class, your second case is a call to a static function.
Static should be used with care and the use of it is very often a sign that refactoring/redesign is necessary.
The point of object oriented programming is to model the world by writing classes (blueprints) and then create as many independent instances of that class with the word new as needed. Each instance is a little organism with the DNA of the class and you can call the same class method on every single instance without influencing the other instances.
A static call however is not related to an instance of a class and therefore there is no object being used. It's a global call of some tool functionality and in fact breaks the idea of encapsulation.
So, I'm not saying there are no use cases for static classes and methods but they should be used with care.
new is the keyword to instantiate the class. If you want to use a method without an instance of the class, it should be a static method. to have a static method, declare the method as static.
class foo
{
public static function bar()
{
return 'hello!';
}
}
How to use it?
echo foo::bar(); //Will print hello
You could make testfunc static and call it like so:
class newclass{
public static function testfunc{
return '1';
}
}
echo newclass::testfunc();
There is nothing like this echo testfunc->newclass(); and doing it like
$class = new newclass();
echo $class->testfunc();
is the proper way to do it when the method is an instance method and not a static one. Note, there is no ability to reference $this within the static method.
You can create a static wrapper for the constructor which would allow for chaining method calls on the same line.
<?php
class ClassA {
static function create() { return new self(); }
function method1() { ... }
}
ClassA::create()->method1();
you can include the php file that contains your functions
<?php
//print.php
function printHello(){
echo "Hello world";
}
?>
then include it and call the function...
<?php
include "print.php";
printHello();
?>
Related
Let's say I have a class:
class test {
public static function sayHi() {
echo 'hi';
}
}
Call it by test::sayHi();
Can I define sayHi() outside of the class or perhaps get rid of the class altogether?
public static function sayHi() {
echo 'hi';
}
I only need this function to encapsulate code for a script.
Maybe the answer is not a static method but a plain function def?
A static method without a class does not make any sense at all. The static keywords signals that this method is identical for all instances of the class. This enables you to call it.. well.. statically on the class itself instead of on one of its instances.
If the content of the method is self-contained, meaning it does not need any other static variables or methods of the class, you can simply omit the class and put the code in a global method. Using global methods is considered a bad practice.
So my advice is to just keep the class, even if it has only that one method within. This way you can still autoload the file instead of having to require it yourself.
Functions in OOP are public by default, you can modify them to private like:
private function test(){
//do something
}
Or like you said, to static, in public or private like:
private static function test(){
//do something
}
But if you're not using OOP, functions by default are global and public, you can't change their access to private. That's not the way they are supposed to works because if you change their type to private, you will NEVER be able to access to that function. Also, static doesn't works because is another property of OOP...
Then, you can simply create that function and access it from everywhere you want (obviously where is available :P because you need to include the file where is stored)
For example, I have a class
class MyClass
{
public $something = 'base';
public function __construct()
{
$something = 'construct';
}
public function __destruct()
{
$something = 'destruct';
}
public static doSomething()
{
$return = new MyClass;
echo $return->something;
}
}
So, my question is this... Will running the static method without instantiating the object run the constructor? If I had, for example, database connection information in the constructor, could I run a static method that returns a query withing explicitly instantiating the class?
Thanks in advance
Yes the construction will be called in your example. Since you already have the code, I guess it would be easy to test.
If you execute MyClass::doSomething(), it will create object of MyClass and, of course, its constructor will be called. Why not to run it and see the result?
I'm lacking PHP knowledge, but compared to other OO languages it will of course run the constructor, because you tell the static method to create a new instance of MyClass.
The same would apply if you called a new SomeOtherType. The code itself doesn't care if it's inside a static/public/private method, as long as new is there, the constructor is invoked.
I did not ask the question correctly, but the answer is that as long as the object is instantiated, even within a static method, the constructor will run. The output would be whatever is in the constructor as the deconstructor does not fire until after the last call to the class.
Sorry for the confusion in the question.
I have two classes that I use to access two different tables in my db. They both have a similar constructor that looks like that:
function __construct($db) {
$this->db = $db;
$userDAO = DAO_DBrecord::createUserDAO($this->db);
$this->userDAO = $userDAO;
}
The other class has the same constructor except that it uses createOtherTableDAO($this->db).
I am planning on having a couple other such classes, and it would be convenient if I could have them all inherit the same constructor, and pass createAppropriateTableDAO as an argument.
To clarify, in the first case above, createUserDAO($this->db) is a static function that calls a constructor in my DAO class. The function in the DAO looks as follows:
public static function createUserDAO($db) {
return new DAO_DBrecord($db, 'users');
}
I use this method to make sure the user model can only call a DAO on the users table.
I'm somewhat of a beginner, and I don't think I have ever seen anything like what I want.
Move the code to create the DAOs into a Factory and then inject the DAOs instead of hard coupling them into whatever these classes are supposed to represent. Or rather create the various Table Data Gateways ("classes that I use to access two different tables") as a whole in the Factory, e.g.
class TableDataGatewayFactory
…
public function create($gatewayName)
{
switch ($gatewayName) {
case 'user':
return new TableDataGateway(new UserDao($this->db)));
break;
default:
throw new Exception('No Gateway for $gatewayName');
}
}
}
As for $this->db, either pass that into the Factory via the ctor or move the creation into the Factory as well. It's somewhat doubled responsibility, but tolerable given that this Factory revolved around creating Database related collaborator graphs.
Apart from that: yes, call_user_func(array('ClassName', 'methodName')) would work. See the manual for
http://php.net/call_user_func and
http://php.net/manual/en/language.pseudo-types.php#language.types.callback
To answer your question first: No, you can't (without resorting to evilCode) pass a function name as a parameter.
But: What you want to archive is a poster-child-issue for an object oriented approach using inheritance.
You'd need a base-class:
class BaseClass
{
function __construct($db) {
$this->db = db;
}
}
and your implementations :
class MyClass extends BaseClass
{
function __construct($db) {
parent::__contruct($db);
$this->userDAO = DAO_DBrecord::createUserDAO($this->db);
}
}
Just for the record: the evilCode would have been
a) you could encapsulate your function in a create_function that can be used as an argument.
b) you could pass the function name as a string to your function and then pass it to eval in the receiving function.
But remember: When eval or create_function looks like the answer you're probably asking the wrong questions!
See: related question
There are several methods which you can use if you feel it necessary to pass the function name or indeed the function itself as a parameter of a function.
call_user_func($function,$args);
call_user_func is one of Php's native functions for invoking methods or functions which takes a function name and optional arguments parameter.
The functionality of call_user_func (when not pertaining to object methods) can be replicated without the using call_user_func using a variable with the string literal of the function name. For example:
function some_func()
{
echo "I'm a function!";
}
$function = "some_func";
$function(); /*Output: I'm a function!*/
And if you're feeling adventurous you can go a bit further and pass a closure / anonymous function as instead of the function name. For example:
$function = function()
{
echo "I'm another function!";
}
$function(); /*Output: I'm another function*/
You can achieve such behavior by using:
call_user_func
eval any literal
i'm php coder, trying to get into python world, and it's very hard for me.
Biggest enjoy of static methods in php is automatic builder of instance. No need to declare object, if you needed it once, in every file (or with different constructor params , in one line)
<?php
class Foo {
function __constructor__(){
$this->var = 'blah';
}
public static function aStaticMethod() {
return $this->var;
}
}
echo Foo::aStaticMethod();
?>
we can call constructor from static method don't we? and we can access everything in class as it would be simple method ... we can even have STATIC CONSTRUCTOR in php class and call it like so: Object::construct()->myMethod(); (to pass different params every time)
but not in python???? #staticmethod makes method in class a simple function that doesn't see totally anything ??
class socket(object):
def __init__(self):
self.oclass = otherclass()
print 'test' # does this constructor called at all when calling static method??
#staticmethod
def ping():
return self.oclass.send('PING') # i can't access anything!!!
print Anidb.ping()
I can't access anything from that god damned static method, it's like a standalone function or something like this..??
Maybe I'm using the wrong decorator? Maybe there's something like php offers with static methods in python?
1) Please tell why static methods is isolated
2) Please tell me how to make the same behavior like php static methods have.
3) Please tell me alternative practical use of this, if php static methods behavior is a bad thing
P.s. the goal of all this to write totally less code as much as possible.
P.p.s Heavy commenting of sample code is appreciated
Thank you.
static methods in PHP are not as you believe, they can't access to instance members. No $this! with them.
<?php
class Foo {
public static $var = 'foo ';
function __construct(){
echo 'constructing ';
$this->var = 'blah ';
}
public function aMethod() {
return $this->var;
}
public static function aStaticMethod() {
#return $this->$var; -> you can't do that,
# $this can be accessed only in instance methods, not static
return self::$var;
}
}
$foo = new Foo();
echo $foo->aMethod();
echo Foo::aStaticMethod();
?>
Python has three kind of methods in objects static methods are like functions defined ouside classes, the only use to put them in object is to keep them with the class as helper functions. class methods can access only to variables defined in the class (decorator #classmethod). This is more or less what PHP calls static members or methods. The first parameter of such methods sould be cls, and content of class can be accessed through cls. Normal methods must get self as first parameter and are the only ones to be able to access to instance members.
If you want several objects of the same type you definitely need instances, and the other types are not what you are looking for. If you only have one instance of an object, you could use class methods instead (or PHP static methods).
But in most case you should not bother doing that if you don't know why and just stick with instances of objects and normal methods, doing otherwise is premature optimization and your code is likely to bite you later because of the many restrictions you introduce.
You want classmethod instead. That provides the class as the first argument.
EDIT:
class C(object):
foo = 42
#classmethod
def printfoo(cls):
print cls.foo
C.printfoo()
I see you've already accepted another answer, but I'm not sure that it will work with your code. Specifically, the oclass variable is only created for instances of the class, not for the class itself. You could do it like this:
class socket(object):
oclass = otherclass()
#classmethod
def ping(cls):
return cls.oclass.send('PING')
socket.ping()
However, using your existing code and removing all decorators, you could simply instantiate it and use a method on the same line:
socket().ping()
There was an interesting question in a practice test that I did not understand the answer to. What is the output of the following code:
<?php
class Foo {
public $name = 'Andrew';
public function getName() {
echo $this->name;
}
}
class Bar extends Foo {
public $name = 'John';
public function getName() {
Foo::getName();
}
}
$a = new Bar;
$a->getName();
?>
Initially, I thought this was produce an error because static methods can not reference $this (atleast in PHP5). I tested this myself and it actually outputs John.
I added Foo::getName(); at the end of the script and did get the error I was expecting. So, what changes when you call a static method from within a class that extends the class you're calling from?
Would anyone mind explaining in detail exactly what is going on here?
Foo::getName() is using an older PHP4 style of scope resolution operator to allow an overridden method to be called.
In PHP5 you would use parent::getName() instead
It's useful if you want to extend, rather than completely override the behaviour of the base class, e.g. this might make it clearer
class Bar extends Foo {
public $name = 'John';
public function getName() {
echo "My name is ";
parent::getName();
}
}
If you call the static method bound to the other object, the method is executed in the context of the current object. Which allows access to the $this-object.
Better way to call the superclass-method from inside the subclass would be:
parent::getName();
$this to the object in whose context the method was called. So: $this is $a->getName() is $a. $this in $fooInstance->getName() would be $fooInstance. In the case that $this is set (in an object $a's method call) and we call a static method, $this remains assigned to $a.
Seems like quite a lot of confusion could come out of using this feature. :)
When you call $a->getName() you're referencing a specific object, $a, which is of class Bar and so returns "John".
Foo::getName() isn't valid outside the function because there's no specific object.
I'm not sure it works in PHP, but if you cast the object to the superclass as in (Foo)$a->getName() then you'd get "Andrew" as your result. You'd still be talking about the specific object ($a) but in this case of type Foo. (Note you wouldn't generally want to do this)
Sometimes programmers are better at explaining things in code than in English!
The first thing going on here is the concept of overloading. When you instantiate Bar, it's getName() method overloads the method of the same name in Foo.
Overloading is a powerful and important part of OOD.
However, it is often useful to be able to call the version of a method that exists in the Parent class (Foo).
Here's an example:
class Dog
{
public function getTag()
{
return "I'm a dog.";
}
}
class Skip extends dog
{
public function getTag()
{
return Dog::getTag() . " My name is Skip.";
// I'm using Dog:: because it matches your example. However, you should use parent:: instead.
}
}
$o = new Skip();
echo $o->getTag(); // Echo's: "I'm a dog. My name is Skip."
Clearly this is a very parochial example but it illustrates a point.
Your base class is the most general implementation of a Type. In this case, it's "Dog." You want to put information in this base class that is common to all instances of that Type. This prevents duplication in each of the Derived classes (like "Skip").
Your script is taking advantage of this feature, perhaps inadvertently.