What's the difference between creating a Global function in a Namespace (and calling it from the global namespace):
<?php
namespace MyNamespace {
function MyFunction($x, $y) {
return $x + $y;
}
}
namespace { //global code... in a new file
var_dump(MyNamespace\MyFunction(1,2));
}
and creating a static class method, and calling from the global Namespace?:
<?php
class MyClass {
public static function MyFunction($x, $y) {
return $x + $y;
}
}
var_dump(MyClass::MyFunction(1,2));
Is there any reason to prefer one method over the other?
Is there any reason to prefer one method over the other?
(below assumes you're asking/referring to a difference between a static class method and a function in a namespace)
Historically (before namespaces arrived), people were forced to use classes with static functions to not pollute a global namespace. This is one of the reasons you're likely to encounter this method more often.
You might prefer to use a static method if you need access to class's data or if you think of leaving a door to overriding them in descendant classes (the so-called 'flexibility and functionality' by some).
You might prefer a namespaced function when all you want is ...uh, ahem... a function. Think of some util, functional or collections functions like compose/partial, retry , filter/map/some/every etc. You are probably not expecting this to be overwritten in a child class, right? Neither it need access to some static class member.
There is one particular annoying problem with (namespaced) functions though, that classes don't suffer from. And it's autoloading. To put it short, there is no way to autoload a function at the moment. And this is another reason you'd likely encounter classes with static methods (when they don't necessarily need to be) more often in practice.
The primary difference is the global namespace can only ever have one function named MyFunction.
Using namespaces, each namespace can have it's own copy of MyFunction. This allows you to flexibility to create a common API without having to come up with clever names.
For example:
namespace Mail {
public static function send() {
// Send Mail
}
}
namespace SMS {
public static function send() {
// Send Text Message
}
}
That wouldn't be possible with a single global namespace. But now you have a predictable interface to call Mail\send() or SMS\send().
For classes, the ability to create these contracts works much better than functions within a namespace, because you get the ability to build interfaces and use abstraction.
For example:
abstract class Mail {
public static function send() {
// Create empty implementation (have to do this because it is static)
};
}
class MailChimp extends Mail {
public static function send() {
// Send Mail
}
}
class MailGun extends Mail {
public static function send() {
// Send Mail
}
}
With that, we can now namespace things under "Mail", but also effectively under the specific implementations of mail, and keep the common send() API we've come to know and love.
Is there any reason to prefer one method over the other?
Either will work. You just get more functionality and flexibility when dealing with classes.
Related
This question already has answers here:
Difference between dependency injection and dependency inversion
(4 answers)
How implement composition in php
(2 answers)
Prefer composition over inheritance?
(35 answers)
Are traits not simply composition?
(4 answers)
Closed 12 months ago.
I have two subclasses and I want to call a method in one subclass from another. Is the only solution to start chaining my classes in order of dependence? Sorry for the noob PHP question. Basically it's a common scenario to have multiple "base" classes such as an email class in which other subclasses will need access to. So do you just starting chaining them?
// BaseClass.php
require_once("./services/checkout.php");
require_once("./services/email.php");
class Base {
// ...
}
// checkout.php
class checkout extends Base {
public function onCheckout() {
// Call send email
$this->sendEmail($email); // <- How to do this?
}
}
// email.php
class email extends Base {
public function sendEmail($email) {
// Send email
}
}
I think it's common to have BaseAction or BaseController but not something as generic as BaseClass. It feels more intuitive to have something like:
class Checkout
{
public function onCheckout(Mailer $mailer)
{
$mailer->sendEmail($email);
}
}
class Mailer
{
public function sendEmail($email)
{
// Send email
}
}
This is still very rough. You most likely want an interface, injected into checkout constructor, perhaps automagically with some dependency injection library that implements autowiring:
interface MessengerInterface
{
public function send(string $text): bool;
}
class Checkout
{
public function __construct(
private MessengerInterface $messenger
) {
}
public function onCheckout()
{
$this->messenger->send('Your order blah blah');
}
}
class Mailer implements MessengerInterface
{
public function send(string $body): bool
{
// Send email
}
}
The key phrase here is "composition vs inheritance".
Inheritance represents an "is-a" relationship. You might say that an HTMLEMail is an Email - it's the same kind of thing, but with extra or different behaviour. But it doesn't make sense to say Checkout is an Emailer - they're two different things, neither is a type of the other.
Composition represents a "has-a" relationship. A Checkout might have an Emailer, which it uses to send e-mails. So they are different classes that you "compose" together. That basically means that rather than $this->sendEmail(), you would write $emailer->sendEmail(), where $emailer is another object that's come from somewhere.
The cleanest way to implement "composition" is via "dependency injection", which is mostly a fancy way of saying "passing objects to other objects".
That might be passing it into the individual method:
class Checkout extends Base {
public function doCheckout($emailer) {
// Call send email
$emailer->sendEmail('email#example.com', 'Hello');
}
}
More flexibly, since you might want to use in multiple methods, passing it into the constructor and storing it on a property:
class Checkout extends Base {
private Emailer $emailer;
public function __construct(Emailer $emailer) {
$this->emailer = $emailer;
}
public function doCheckout() {
// Call send email
$this->emailer->sendEmail('email#example.com', 'Hello');
}
}
This kind of setting of properties in the constructor is so common that PHP 8 has a special short-hand for it called "Constructor Property Promotion":
class Checkout extends Base {
// note the "private" keyword next to the argument
public function __construct(private Emailer $emailer) {
}
public function doCheckout() {
// Call send email
$this->emailer->sendEmail('email#example.com', 'Hello');
}
}
More flexibly still, you can depend on an interface, which means "anything that has the right behaviour can be passed in here, I'll decide on the exact implementation later".
The idea is that you can write the Checkout class without knowing what the inside of the Emailer class is going to look like. You just need to know that sendEmail requires certain arguments, and returns certain things when it's done. Then you can have one implementation that uses a username and password to talk to an SMTP server, one implementation that uses an API key to use a web service, and a third that just logs to a local file for test purposes. The Checkout class doesn't need to know how to create each one, or when to use them, it just waits for one to be provided.
Somewhere else, you have some co-ordinating code that actually knows how to create all these objects. The fancy way to do this in a larger project is with a library like PHP-DI that uses configuration and "auto-wiring" to work out what's needed when, but a simple version just looks like this:
$config = parse_config_file('config.ini');
if ( $config['mode'] === 'debug' ) {
$emailer = new DebugEmailer($config['logfiles']['email_debug']);
}
else {
$emailer = new SMTPEmailer($config['smtp']['username'], $config['smtp']['password']);
}
$checkout = new Checkout($emailer);
$checkout->doCheckout();
Please read Traits in Php. It seem that would be the right thing for your goal:
PHP-Traits (php.org)
PHP-Traits (W3Schools - easier to understand)
I would suggest to reconsider your inheritance, whether it makes sense that E-Mail class and Checkout-Class inherit from the same base class. They should do total different and independent things by their own. If you want to send an e-mail from the checkout-class then try to implement an e-mail class and inject an instance of it to the checkout object.
I'm trying to test a method using PHPUnit, where it calls another function (standalone function, without class), which resides in different file which does a some pretty good calculation and returns a object.
This is my actual main code:
class CreateRecords
{
public function createEntities($details)
{
if (trim($details['username']) == "") {
$this->result = "Username is empty.";
} else {
$this->result = create_record($Details['username']);
}
return $this->result;
}
}
This create_record function, (standalone function, without class), which is core function, resides in separate file and it does pretty good calculations (calls lots of other methods/functions) and returns object, whether it is successful or not.
I can mock the createEntities method, but I want to mock the create_record function, which does all the computations and returns the result.
I have seen few posts which has a somewhat similar scenario,
phpunit testing method that calls other class methods which need mock
PHPUnit mock method used in another class
But I am unable to understand, how to mock standalone function which is declared in some different file.
You can create new method that will be returning result from outside function.
Then you can mock this new method
class CreateRecords
{
public function createEntities($details)
{
if (trim($details['username']) == "") {
$this->result = "Username is empty.";
} else {
$this->result = $this->createRecord($Details['username']);
}
return $this->result;
}
public function createRecord($username){
return create_record($username);
}
}
Namespaces in PHP5.3+ offer an excellent solution to this, which allows you to override built-in functions in your current namespace.
Longer term, refactoring the global create_record() into a class which can be injected into your CreateRecords class, and then mocked, would be a good way to go. In this instance, the global function would just be a simple wrapper to call the class until the entire application was updated.
To re-create the create_record($username) is not hard though, and useful for tests. The same technique can be used to override the global time() function as well.
Within the test-file, add a new (but local) namespace:
<?php
namespace Test\DatabaseAccess;
use DatabaseAccess\CreateRecord;
use PHPUnit\Framework\TestCase;
namespace DatabaseAccess {
function create_record($username)
{
// pretend to do something
}
}
class CreateRecordTest extends TestCase
{
// test to check CreateRecord class
// which should call the `create_record`, above
}
This is the same technique that the SymfonyBridge system uses to create ClockMock - which dynamically adds time(), sleep(), etc to the namespace that you are unit-testing (in this example, the namespace DatabaseAccess\CreateRecord, not the Test\ prefixed namespace). ClockMock (and DnsMock) does it with an eval() call, but since you know the namespace explicitly, you can write it into the test file itself for clarity.
After reading the above (pretty good) answers and your comments saying that you cannot touch the tested class - CreateRecords,
I can suggest another solution that is not ideal but should get the job done:
Create a new class that inherits\ extends from CreateRecords - CreateRecordsExtended.
The extended class should override only the tested function in question createEntities($details). so create a new one and copy the code from the original function.
Also, create a new function create_record().
Now, inside the new createEntitied, call your version of create_record - $this->create_record(), instead of calling the global function.
Now you can mock it! and even because this class is used only for testing, you can even just retun whatever you want from it, and do not even have to mock it now.
This class can reside either in the regular code folder, or as a neighbor of your testing class- as it is used only for testing.
Pros:
existing code is not modified at all.
you still use same exact
functionality, besides the mocked function, which is what you wanted.
Cons:
you will be testing a different class then the one you wanted to, but
it still close enough.
code inside function createEntities needs to
be copied
Perhaps its not most ideal, but should get the job done. hope i helped.
Consider the situation where there are multiple classes that all need to have access to the configuration storage mechanism, but cannot be extended from a base class because of the architectuur of the framework.
In addition to that I wanted to keep the storage mechanism flexible (be able to switch storage backend later).
I felt it would make sense to create a trait which does the actual saving and use those functions inside all classes (for the example I use $_SESSION as storage system):
trait MyTrait {
function setting_enabled() {
return !empty($_SESSION['setting']) ? TRUE : FALSE;
}
function enable_setting() {
$_SESSION['setting'] = TRUE;
}
function disable_setting() {
$_SESSION['setting'] = FALSE;
}
}
This works great from classes. There is however also one file that is not a class, but is just plain PHP, for which I also need to know if the setting is enabled.
I have tried declaring the function as static:
trait MyTrait {
static function setting_enabled() { // Declared as static function
return !empty($_SESSION['setting']) ? TRUE : FALSE;
}
...
}
And then call the static function from the trait, which worked fine.
if (MyTrait::setting_enabled()) {
...
}
It however feels not entirely right. On the other hand, creating a new empty class that uses the trait and instantiating that to obtain the value seems like a lot of overhead.
Am I allowed to do this (as of PHP 5.6, but also considering the future with PHP 7.x)?
PHP does not allow calling trait's methods without some class (no matter if static or not).
A simple workaround is to use an anonymous class mediately:
...
(new class { use MyTrait; })::myMethod();
...
I like this way a little bit more because we don't create an unnecessary class name.
If you have a trait then you decided to make a multiple inheritance once, maybe for multiple classes. Otherwise, it's redundant declaration and you have to use a class. In fact, and existing of trait means its using.
If you have a static function inside trait, then why you can't using its from the class you'd implemented trait in?
trait MyTrait {
static myFunc() {}
}
class ThatUsingMyTrait {
use MyTrait;
}
// pretend below a code where you want to use the trait.
if(ThatUsingMyTrait::myFunc()) {
// do something
}
The code also is may be a class you want to implement without trait directly.
Hope I describe the idea understandingly.
unsure to import your trait be truing to resolve it:
In case of non-static method
(new class { use MyTrait; })->myMethod();
but it seem it deprecated on php 8
I have a general problem with this use case: I have a class A. This class has a non-abstract method doStuffCallback() which could be overridden but it's not necessary for every subclass. But: I want to ensure that if the method is overriden the subclass-method must call the parents method.
Example:
abstract class A {
private function doStuff() {
$this->doStuffCallback();
}
protected function doStuffCallback() {
// IMPORTANT CODE HERE
}
}
class B extends A {
protected function doStuffCallback() {
parent::doStuffCallback(); // I want to enforce this because the parents method code is important
// ALSO IMPORTANT CODE
}
}
Because the overridden method does the same thing it would be very ugly to define two methods for the same responsibility and a private helper-method which calls both. Like this:
abstract class A {
private function doStuff() {
$this->callDoStuffCallback();
}
private function callDoStuffCallback() {
$this->internalDoStuffCallback();
$this->doStuffCallback();
// This is VERY ugly
}
private function internalDoStuffCallback() {
// IMPORTANT CODE HERE
}
protected function doStuffCallback() {}
}
class B extends A {
protected function doStuffCallback() {
// IMPORTANT CODE
}
}
This is really ugly and laborious. So my question: Is there a way in PHP to force overriden methods to call the parents method?
No. There is no such language feature in PHP; this restriction is not possible in most subtype-'OO' languages.
Instead programs must rely on explicit documentation contracts; and hopefully, unit testing to ensure conformance.
Guards may also be employed such that, at some point by and by when a method on the parent class is used, it could throw an exception if the 'current state' is not valid (eg. such and such a method has not been called yet). This may also be made more explicit by making the subclass required to call (as defined in the documentation contract) some special method, instead of simply the overriden super method. However, such is outside of any type system.
While the self:: scope could be used (eg. call non-overriden method which calls overriden method), this would involve further magic (eg. some stack state) to avoid infinite recursion loops; and it would be as easy to accidentally omit usage.
My recommendation is to call a (private) method that calls this 'maybe overriden' method in relationship to whatever logic applies, as shown in the example (although hopefully with more task specific tames). Then the (protected) overriden method is not expected or required to handle any of the special logic itself; nor is it meant to be called directly outside of the context established by the parent class - it is just what it currently claims to be, a special callback.
I tend to disagree with "This is VERY ugly". It is the standard way of handling this use case and a variant of the Template Method Pattern.
Now I am just guessing because you did not provide a real example but if you say that the two methods "do the same thing", there might be something wrong with your design. If they do the same thing, why is calling the parent implementation necessary if the subclass does the same thing in a different way? To me it sounds like the method actually does more than one thing and you might be able to break it down into several parts that can be overridden individually (or not, then make them private or final).
I know this is an old topic but I was asking myself the same question and what I did is :
abstract class A {
private function doStuff() {
$this->doStuffCallback();
}
final protected function doStuffCallback() {
// IMPORTANT CODE HERE
$this->callNewFunction();
}
abstract protected function callNewFunction();
}
class B extends A {
protected function callNewFunction() {
// ALSO IMPORTANT CODE
}
}
So basically I would mark as "final" the function you wish to force the code for every child and then call a new "Abstract" function to force the childs to implement it. If you do not wish to force the new "Abstract" function, simply don't make it abstract.
Edit : This is basically #Fabian Schmengler's answer but more concrete with your example.
No, you can access, you can use method for parent, like this
<?php
class A {
function s1($p1) {
echo 's1: '.$p1;
}
}
class B extends A {
public function callParent($method, $p1) {
parent::$method($p1);
}
}
$b = new B();
$b->callParent('s1', 'param1');
or replace extending on magic methods __call and etc. https://github.com/StagnantIce/php_extend_magic/blob/master/AExtendClass.php
Assuming that I have to create a class that takes some text do some processing and return it ... with no dependency and it's a stateless class..
I'd like to know would be better to create a stateless class without constructor or just create a static class (in php it's just Static methods)
class like this:
class ClassName
{
public function processText($text)
{
// Some code
$text = $this->moreProcessing($text);
return $text;
}
protected function moreProcessing($text)
{
return $text;
}
}
and this:
class ClassName
{
public static function processText($text)
{
// Some code
$text = static::moreProcessing($text);
return $text;
}
protected static function moreProcessing($text)
{
return $text;
}
}
I Know that dependency injection into the class where these classes are used would be better but assume that I just won't have dependency injection..
My question is mainly would it be better to create static class for the simple example above?
Practically you will see no difference whatsoever.
It's only in the syntax, and the ability of a constructor to perform stuff automatically, though you still have to create instances to invoke the constructor, which in this case is not far off calling some equivalent static member function.
However, non-static member functions are supposed to affect internal state so, if you have no state, static member functions seem more conventional, and will be slightly less surprising to users of the class.
The best approach, though, is to stick your functions in a namespace. Classes are for data and functions operating on that data... even static ones.