Methods defined outside class? - php

I am wondering if php methods are ever defined outside of the class body as they are often done in C++. I realise this question is the same as Defining class methods in PHP . But I believe his original question had 'declare' instead of 'define' so all the answers seem a bit inappropriate.
Update:
Probably my idea of define and declare were flawed. But by define outside of the class body, i meant something equivalent to the C++
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area () {return (x*y);}
};
void CRectangle::set_values (int a, int b) {
x = a;
y = b;
}
All the examples of php code have the the code inside the class body like a C++ inlined function. Even if there would be no functional difference between the two in PHP, its just a question of style.

Here is a terrible, ugly, hack that should never be used. But, you asked for it!
class Bar {
function __call($name, $args) {
call_user_func_array(sprintf('%s_%s', get_class($this), $name), array_merge(array($this), $args));
}
}
function Bar_foo($this) {
echo sprintf("Simulating %s::foo\n", get_class($this));
}
$bar = new Bar();
$bar->foo();
What have I done? Anyway, to add new methods, just prefix them with the name of the class and an underscore. The first argument to the function is a reference to $this.

I stumbled upon this question while looking for a way to separate declaration and implementation of class methods. Why? For the sake of code readability. When the declarations are in a separate file, or at the top of the class file, someone looking to use the class does not have to wade through the whole implementation to find out which methods are offered.
I did find something useful though: PHP interface classes. I don't think they are designed for it, but they serve the purpose: an interface class defines all the methods, and then the "real" class implements them. Here's an article about it:
http://www.davegardner.me.uk/blog/2010/11/21/why-you-should-always-use-php-interfaces/

Having the declaration of methods in header files separate from their implementation is, to my knowledge, pretty unique to C/C++. All other languages I know don't have it at all, or only in limited form (such as interfaces in Java and C#)

It's possible, but very, very hacky and not recommended. No reason to do it either.

First of all, in PHP, all class methods must be defined and implemented within the class structure (class x { }). It is in no way like C++ where you have the implementations (*.cpp) separate from the definitions (*.h).

Natively PHP doesn't support features like this, but since PHP5.4 you can dynamically add methods to object. As an example, you can look at this: https://github.com/ptrofimov/jslikeobject

No. You can consider 'declare' and 'define' to be interchangeable in that question.

Related

Why does PHP support calling static functions as non-static member methods?

Code beforehand fully valid code from 5.0.0 (without E_STRICT or E_DEPRECATED)
class A{
static public function b() {
}
public function c(){
$this->b();
}
}
$d = new A();
$d->c();
$d->b();
It's looks like inconsistent behaviour because you cannot use static properties from instance.
The PHP way is to steal and borrow from other languages whenever
possible ...
But I cannot find any programming language that supports similar behavior.
Why does PHP support it? What is the point of calling static methods as non-static?
Some explanation from support: Expected behavior
Actually, C++ and Java support this. It seems the PHP developers, after discussion, decided on implementation to match them.
After a bit of digging, I found this thread from February 2004, which is essentially their discussion about the implementation choices. Important tidbits from the discussion:
From Cristiano Duarte:
C++ allows $a->bar() when bar() is a static method (yes, it is called
in a static context there too).
IMO, there should be no error, warning or notice here.
I Agree. PHP is fine the way it is.
From Art:
Regardless of the final implementation, I think access to static methods and
static class variables should be consistent. Currently, you cannot access a
class variable via an object instance.
And for what it's worth, I see no reason why static methods cannot be called
from objects. Follow Java/C++ in this case.
Ultimately, a final decision From Wez:
Please drop this thread; we're not changing the behaviour of static.
It looks to me that it is just a syntax consideration here. Nothing here is inconsistent with the logic of static methods, it's still impossible to use $this in your static function, and therefore the function will not have access to instance properties or methods. It feels more like a shortcut than an inconsistency to me.
I have no use case of that, but I guess someone may find it useful with objects created with dynamic class names: you can still use the function even if you don't know it's class name.

Should Helper Functions be in a Class?

In my efforts to rewrite a past project of mine with OOP in mind, I have broken my code up into classes such as Devices, Facilities, etc.
Before moving to a more object oriented approach, I just stuck all of my helper functions in an included "functions.php" file. Using Devices as an example, would it be best to have a Devices class for my object specific properties/methods, then have a DeviceManager class to store functions like getDeviceByName, getDeviceByID, etc?
From what I am understanding, OOP is more about readability/manageability than anything else, why I assume the purpose would just be to have something like DeviceManager::GetDevice("Computer1") in place of GetDeviceByName("Computer1")
If you are thinking of using a class as a namespace then you can just as well use an actual namespace:
namespace MyCollectionOfFunctions;
function printMyName($name) {
echo $name;
}
And then you can use the functions like this:
use MyCollectionOfFunctions as fn;
echo fn\printMyName('Brett Powell');
There is nothing wrong with functions. Do not let anyone tell you that they belong is a class, as static methods. It can be done that way, but since we got namespaces there really is no reason for it.
In a OOP languages like C# or Java, you simply can't have functions outside a class, so there's no issue. That doesn't mean you're doing OOP, which is a mindset.
In PHP you can either put the relevant functions into a nampespace or within a class (inside a namespace). It's up to you, there's no right or wrong approach. Personally, I'd put them into a class because that's how I'm doing it in C# and it'll help a bit with productivity: I group related functionality in one place (class). It's easier to manage.
But strictly from a programming point of view, there's no difference, your code won't be cleaner/decoupled or more OOP because you've put functions into a class or namespace
A few advantages when using Namespace or Class for static functions.
Namespace and Class Name helps distinguish functions. You can avoid naming conflicts.
DPDate::FirstDayOfMonth() is better than FirstDayOfMonth() when you want to take advantage of auto suggestion of the IDE.
It is really all about cohesion and decoupling.
You must following this rules:
In OOP you MUST ALWAYS use a CLASS
Your method must have a single responsability
Avoid generic helper classes, classes must have a simple and specific responsability
Don't use static methods, use strategy (pass the object throw the param) to call a method, this way you can create a Mock to test your methods.
Avoid private methods, this make dificult to test your classes
Keep this things in mind, and you will gona make a clean code. =)
Answering Eric about item 4: This code it will use static method:
public function myFunction() {
$deviceId = DeviceManger::getDeviceId('computer 1');
// Rest of code using the device id
}
This way i cant mock the return of Device ID, this way i can:
public function myFunction(deviceManger) {
$deviceId = deviceManager->getDeviceId('computer 1');
// Rest of code using the device id
}
The code with mock in test function:
$deviceManager = $this->getMock('DeviceManager');
$deviceManager->method('getDeviceId')->returnValue(1);
myFuncion($deviceManager);

How do I Use Inner Classes in PHP?

I'm from a Java background, and I want to use an inner class in php. Every time I put the inner class though, I get a syntax error. Is this possible with PHP? Also, how do I reference the outer class? Do I get access to ALL its data members?
<?php
class OuterClass {
var $x = 15;
function __construct() {
}
class InnerClass { // error when InnerClass is static
function __construct() { // error when InnerClass is static
echo $x;
}
}
}
?>
This is used for a MoveClass (as in make a move) of a specific card game. I think it'd be good design to put these classes together because they don't make sense apart. Also, the MoveClass needs to know about some data members of the Game class. Why not make it a function? It's simply too big.
Edit:
What about nested classes? From what I understand, those have to be static? O_o
PHP does not allow for inner classes. Should you wish to access all of the data members from the parent class, I would suggest you employ Inheritance.
A possible alternative:
class OuterClass {
var $x = 15;
function __construct() {
}
}
class ChildClass extends OuterClass {
function __construct() {
parent::__construct();
}
}
You can envoke a method form the parent class by referring to the class itself; In PHP you can do this with the parent keyword. So, to refer to a method in the context of a class rather than an object we use :: as opposed to ->.
in PHP 5.4 or later, you can use PHP Traits which are designed more for multiple inheritance, but may suit your needs. From the PHP Documentation:
A Trait is similar to a class, but only intended to group
functionality in a fine-grained and consistent way. It is not possible
to instantiate a Trait on its own. It is an addition to traditional
inheritance and enables horizontal composition of behavior; that is,
the application of class members without requiring inheritance.
http://php.net/manual/en/language.oop5.traits.php
As mentioned in comments to this answer from another question, the PHP version of this functionality has been added in PHP 7. It does not seem to provide exactly what you are asking for. However, it should provide you a similar design pattern.
Here's the RFC describing how it works: https://wiki.php.net/rfc/anonymous_classes
As mentioned in the other answer's comments, search the RFC page for "nested" to see an example of nesting inside an outer class.
You might want to use a stdClass instead. Here's an SO question about it: What is stdClass in PHP?
You can't nest classes like that.
Look at the "extends" section of the manual.

How to have a class spread across many source files?

I am currently working on a PHP project which includes extensive database usage. The basics are: I have a PDOFactory class which follows the Factory pattern and an abstract SQL class with static methods (just a container for those methods) which in turn talks to PDOFactory
As I said, the project involves extensive database usage, so the SQL class will contain numerous methods. However, they could be easily grouped, depending on what they deal with (i.e. session storage, user logging on/off, etc.). That would make the SQL class much easier to maintain and so on and forth. And here comes the big question: Can I have the source of the class contents spread across many files? There could be (at least) two possible solutions to this problem:
Multiple inheritance, i.e. having classes SQLSession, SQLUser, SQLblahblah and making the SQL class inherit all of them.
C++-like pre-processor* directives, i.e. #include SQLSession.php; or something like that.
I know there is no multiple inheritance in PHP, so that rules out option No. 1. Is option No. 2 even possible? Or does anybody know of better solutions to this problem?
*Or actually pre-pre-processor directives, since PHP is a pre-processor. :)
EDIT:
Here's an attempt to answer this question, based on Kalium's suggestion. It's a mess to read, but it works. However, I'm gonna stick with Bill's method as it's way cleaner.
class SQL {
private static $oInstance = false;
public static function getInstance()
{
if( self::$oInstance == false )
{
self::$oInstance = new self();
}
return self::$oInstance;
}
public $SESSION;
private function __construct()
{
$this->SESSION = new SESSION;
}
}
// this would be in another file
class SESSION {
public function printOne()
{
echo "One";
}
}
SQL::getInstance()->SESSION->printOne(); // outputs "One"
?>
I think you may be approaching this wrong. That's certainly not the best way to go about it. Try breaking the many functions into smaller utility classes and then using those to composite a larger class.
Don't use static methods, as it makes it hard to use something else than the SQL class
Use small classes, which have a single responsibility.
I think you should use the Builder pattern for your SQL instead of a motley container of static methods.
No, there is no multiple inheritance in PHP. Use delegation instead.
No, you can't include files to define methods of a class. You can only include files in contexts where code is executing, not in the middle of a class definition:
<?php
include("define-functions.php"); // OK
class Foo
{
include("define-methods.php"); // ERROR
function foo()
{
include("method-body.php"); // OK
}
}
PHP Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION
in foo.php on line 7
Re your comment:
Since you're committed to using only static methods, why bother with a class at all? Just define functions in the global scope. Then you can include() as many as you want:
<?php
include("SQLSession.php");
include("SQLUser.php");
include("SQLblahblah.php");
SQLSession.php:
<?php
function SQLSessionStart()
{
...
}
function SQLSessionEnd()
{
...
}
You don't have access to static class member data with this solution, but you can just use global variables.
to me, it sounds like you're trying to create a monolithic chunk of code, which is the exact opposite of class based OO code - I'd recommend following the DAO blueprint of the Java core patterns, and implementing it in PHP for what you want to do :) that should cover all you're questions

PHP initialize variable in __construct() vs declaration

i wonder if there is any difference between
class TestClass {
private $_var = "abc";
}
vs
class TestClass {
private $_var;
function __construct() {
$this->_var = "abc";
}
}
i wonder if the latter is the preferred way/better practice? is there any functional difference?
They're effectively the same. I prefer the former, because then there's only one place to look for the value and its default.
On the other hand, if you need to do something dynamic with it or set it to anything other than an array or primitive, you need to use the second form. Notably, you can't use a function call to declare a variable in the first form.
Excellent question! I feel like the first example is more correct, if you already know the initial value of the object's attribute, why would you want to declare it in the constructor?
I feel like the purpose of the constructor is to set attributes that may be variable.
If anything, it seems like a readability thing. I don't know of any performance issues with either method.
I am not aware of any differences in your examples, they both seem to behave the same. if you do both, constructor code overrides the initialization done in the declaration section.
Personally I come from C++ background and in statically typed languages all declarations happen inside the body of the class but outside of any functions, and all initializations and other class prep happen inside the constructor.
When initialization is done as in your first example and there is some code doing something in constructor as well, to me it looks like mixing coding paradigms, so even though it is more verbose, I tend to pick your second example for my own style of code.

Categories