I have a MyTranslatable trait, which uses another OtherTranslatable trait, the one from a third party package. I'm including them as follows.
trait MyTranslatable
{
use OtherTranslatable {
OtherTranslatable::method as public otherTranslatableMethod;
}
public function index()
{
// Perform my actions
// Call otherTranslatableMethod
static::otherTranslatableMethod();
}
I'm wondering if this is valid, the code is working but I'm not so sure if traits are meant to be used this way, and if this is the correct way to call the "parent trait's" method like this after my actions are complete
I think your code from architectural point of view is correct since child blueprints (classes, traits) in PHP can override in use statement of the context, the methods from already used traits (I avoid call this inheritance because using trait is actually copy-paste), but I don't find quite necessary to invoke your otherTranslatableMethod() statically in MyTranslatable (of course except if it's defined as static in OtherTranslatable trait).
If you have non-static definition of OtherTranslatable->method() you can do the following in order to make your code more correct and clean.
trait MyTranslatable
{
use OtherTranslatable {
method as public otherTranslatableMethod;
}
public function index()
{
// Perform my actions
// Call otherTranslatableMethod
$this->otherTranslatableMethod();
}
}
Hope this helps.
Related
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
I have seen the following code:
class LoginAuth
{
function __construct(AuthInterface $auth)
{
$this->auth = $auth;
}
function userLogin ($credits)
{
return $this->auth->login($credits);
}
}
My Question is that Interfaces as described by PHP is:
Object interfaces allow you to create code which specifies which methods a class must
implement, without having to define how these methods are handled.
So, we see that interfaces are not used to define an internal logic of a [class'] controller, they just allow for definition of which methods should be implemented by a certain class.
How then it could be possible that, an interface which does not contain any actual logic inside the methods, be deployed. I mean, the method login() which is a member of auth() class is defined in an interface:
interface AuthInterface ()
{
function login($credits){}
}
Then how such signature could be used (as it is used in the main example)?
Within a single class, I am able to use the _call/_callStatic functions to call a function before any function is actually run. However, I'm yet to find a solution that I can apply to the parent, and it will be inherited by the children.
The only method I can think of is putting a small snippet of code within each class that calls a function in the parent, which contains my code.
Are there any better solutions that I can implement?
As long as you are at least on php 5.4, you could use traits.
http://php.net/traits
This will need some adjustments in your code but could allow the desired behavior.
Do you have some more information on your use case? I think of logging from your description, is this correct?
Unfortunately there are not magic methods in PHP which get run whenever any method is called.
I think the solution you are looking for is a decorator, see this article for the tips on decorating methods / classes in PHP.
how to implement a decorator in PHP?
It's hard to help you without seeing some code. However, assuming that you don't re-define __call/__callStatic in the subclass, it should simply inherit the method from it's superclass.
If you do re-define __call/__callStatic in the subclass, it overrides the superclass' definition. So you'd somehow have to call the superclass' method. In order to do this you can use the parent keyword. See this example:
class SuperClass
{
public function __call($name, $arguments)
{
// Do some stuff
}
}
class SubClass extends SuperClass
{
public function __call($name, $arguments)
{
// Execute the parent's __call() method
return parent::__call($name, $arguments);
// Do some extra stuff here
}
}