add static key word dynamically before the function - php

I want to like something :
if(true)
define("M_STATIC", "static");
else
define("M_STATIC", "");
class A
{
M_STATIC function() // this is not allowed.
{
//do something my task
}
}
I think, you know.... what i want. :)
I'm using a CMS. and new version of
CMS is changed with some function
declaration.(like old cms not have
static but new version have) so i
think, my page should be compatible
both version (this class extends by CMS class and this function is override to parent function )

This is just not possible, actually : a method is static, or is not ; but it's something thats defined at compile-time, and not at execution-time.
And, in PHP, there is no pre-processor (like you'd have in C, for example), to do the kind of replacements you are asking.

Since the new version is static but the old version wants non-static, I'd define it static and then create an instance method that simply calls the static one for backward compatibility.

I am not sure doing something like this is possible(Which I do not think so) , even if it is possible ,It is not a good practice in OOP, it will make your code very difficult to understand and adds complexity to it.
I am not sure what you want out of this bit if you want need a static function create a class to hold a static one and another class which holds non static functions.

Related

Anyone know of a PHP Magic Constant for Trait's Redefined Name in a Class?

To make it simple, I have noticed that PHP doesn't seem to offer any magic constant for determining what the name that a trait has been changed to in a class. Since this sounds confusing to me in words, I will give an example, as it is rather easy and would expect it to be somewhere in the new PHP 5.5, I don't see a way to doing it. So here it is:
Say we have some class, that uses some trait that conflicts with some function inside the class, example:
class SomeClass {
use \Name\Space\SomeTrait { SomeFunction as private NewFunctionName; }
function SomeFunction() {
$this->NewFunctionName();
}
}
Since, obviously this class has the "SomeFunction" function, and we are aware that inside of SomeTrait we have included, is a function that is matching by name to a function we have inside this class. Now, since the "SomeFunction" came into this class via a trait inside of a \Name\Space, these 2 functions do 2 different things, but happen to use the same name, and inside of either another function or literally our 'SomeFunction', we then use the "SomeFunction" from our trait, by calling it by the "NewFunctionName".
So hopefully I haven't lost anyone here, as here is what my question comes down to in the above scenario. Within the \Name\Space\SomeTrait\SomeFunction(), how could one get the "NewFunctionName" that this trait function was assigned too? One would think to use a magic method, such as __FUNCTION__, or __METHOD__, or even __TRAIT__, except none of these give the expected result, so does anyone know a way to get this information without passing it to the function as a parameter and resulting in a hacky code? Maybe PHP 5.6 needs to add a new Magic Constant __AS__, or adjust the result of __TRAIT__, I dont understand why __TRAIT__ and __FUNCTION_ need to return the same information (or nearly the same information). Any help would be awesome, if it is an unconventional hacky method, Im interested in seeing my options, until I can open up a bug report with php regarding this. (if it is truly a bug)
edit:
My current, least hacky, method seems to be,
debug_backtrace()[0]['function']
and though it works, I feel it is doing a lot to get a simple string, especially if you use the function a lot. :/
This is the solution I ended up using. It's not very good but probably better than using the debug_backtrace function.
Problem example:
Trait ExampleTrait {
protected function doSomethingRecursive() {
// this is a problem because it could be renamed
$this->doSomethingRecursive();
}
}
Solution example:
Trait ExampleTrait {
protected function doSomethingRecursive() {
// this is a problem because it could be renamed
$this->__internal_doSomethingRecursive();
}
private function __internal_doSomethingRecursive() {
// this works because the class would have
// used and renamed the above function
// but this "internal" function *should*
// remain available under it's original name
$this->__internal_doSomethingRecursive();
}
}
Of course it's possible to break this but for most cases it should be fine. You could also include the name of the trait in the internal function name to further prevent conflicts.
Your current solution is going to be the best, with a couple tweaks:
debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,1)[0]['function']
The DEBUG_BACKTRACE_IGNORE_ARGS and the frame limit of 1 there will make the backtrace shallow, faster, and use less memory.

Open / Closed principle - How to call the new versions?

I'm trying to grasp the Open/Closed principle (in my case for PHP, but that shouln't really make a difference).
The way i understand it is that a class is never open for modification. Only for bug fixing. If i wanted to add new code to the class, then i'd have to create a new one and extend the 'old' class. That's the only way i can add new code to it.
In a way i can see the advantages of this. Because basically you create some sort of versioning system, where old code always work, but you can always try to use the new classes too.
But how does this work in practice? I mean, suppose i have the following class:
class MyObject
{
public function doSomething()
{
echo 'Im doing something';
}
}
So somewhere i'm probably instantiating this class:
$obj = new MyObject();
But then i decide that it's good to have another method in that object. So i can do something else too. According to the OCP i can't modify the class. So i have to create a new one, which extends to old one right?
First problem. How do i call the new class? Because it isn't really a complete new object. Like. a User object is a User object. I can't suddenly give it completely diffent name just because it needs another method. Anyway, i create the new class:
class MyNewObject extends MyObject
{
public function doSomethingElse()
{
echo 'Im doing something else now';
}
}
Now this also means i have to change the line of code where i instantiated the "MyObject" class and replace it with the "MyNewObject" class, right..? And if that's done in more than one place, then i have to search through my source code... (Think about a method in a controller class, which almost always uses the 'new' keyword to instantiate certain classes).
The same basically applies to inheritance. I'd have to find each class the inherits the old class and have to replace that with the new class.
So basically my questions are:
How do you name the new classes which have the new methods? Just becasue i added some new functionality, doesn't mean i can give the class a whole new name...
And what if the 'old' classs is instantiated (or inherited) from multiple places. Then i'd have to find all of those places... Where's the gain?
The Open Closed Principle isn't intended to be used as a kind of version control system. If you really need to make changes to the class, then go ahead and make those changes. You don't need to create new classes and change all the places that instantiated the old one.
The point of the Open Closed Principle is that a well-designed system shouldn't require you to change existing functionality in order to add new functionality. If you are adding a new class to the system, you shouldn't need to search through all your code to find the places where you need to reference that class or have special cases for it.
If the design of your class isn't flexible enough to handle some new piece of functionality, then by all means change the code in your class. But when you change the code, make it flexible so you can handle similar changes in the future without code changes. It's meant to be a design policy not a set of handcuffs to prevent you from making changes. With good design decisions, over time your existing code will require fewer and fewer changes when you add new functionality to the system. It's an iterative process.
I would argue that by adding a function, you're not modifying the class behavior.
In all the instances where doSomething() is currently being called in your app, simply by adding doSomethingElse() to the class will have no effect. Since you're not changing doSomething(), the behavior is the same as it was before.
Once you determine that your doSomething() implementation isn't cutting it for certain circumstances, you can extend the class and override doSometing(). Again, the original still behaves the same as it always did, but now you have a new doSomething() to work with also.
I realize that this goes against the strict definition of open/closed, but this is the real world, and that's how I interpreted that principle in my code.
You need to create a constructor in your MyNewObject class which calls the parent class' constructor:
function __construct() {
parent::__construct();
}
This way you can instantiate the new class and still access all the functionality of the extended one.
You can then also override any function in the parent class (as long as it is not marked final of course).
So you could do:
$newObj = new MyNewObject();
$newObj->doSomething();
$newObj->doSomethingElse();

defining a global function in kohana

I am new to kohana and also relatively to php.
I have a simple URI encoding function, which mimics that of JS %100, unlike that of PHP's.
I want to use this function in certain classes but I don't want to define it in each and every one of them.
So, how can I define a global function to be used in all places?
(I don't want to create a class for a 3 line code function)
Thank you!
Overload the core URL helper class. Add your function as a static method.
Override your desire to avoid good OO principles. Create a new class and make a static public function. Don't create bad-old global functions.
<?php
function yourFunction( ) {
return 'your result';
}
How about that? Just write that in a file that always gets included and you're good to go. Don't go making a static class just for the sake of thinking you're doing OO, there's no point.
You can put your global function in you bootstrap (APPPATH/bootstrap.php) though I recommend extending the core URL helper class (assuming you're on Kohana 3.x) by creating a new file at APPPATH/classes/url.php:
class URL extends Kohana_URL {
public static function encode($uri)
{
// ...
}
}
It's almost always worth the 3 lines of code. Kohana was designed for you to override its core classes. Your code will be more maintainable.

How do I make 15 static PHP classes work together well?

I have a personal PHP application that has about 15 classes. Each class is only initiated once as a page is executed. In other words, when the page loads:
15 classes are loaded, and as each class file gets loaded, I create one instance of the class.
The application (so far) is designed so every variable in the system has one state during the generation of a page. I use global vars to access each of these
It's worked fine for 3 years, but I am the sole developer and a goo debugger of my own code.
I have heard all the issues with Singletons, and I hate doing, "global $var" all over the place. Please tell me how to pull this type of structure out and into something developers would love. I want to write software the right way, but I can't seem to find a very simple code framework for this type of execution.
Oh - and I'm not looking for a MVC framework solution. I would love your thoughts on how I take 15 classes and turn them into a proper framework for working together. I would also love an articulation on how "stupid" it is to develop this way.
If you have variables you want all classes to have access to, maybe you could try inheritance, for example something like
class Settings
{
var $page_name = "My Page";
var $database_name = "my_db";
}
and then let all classes inherit this class like
class Page extends Settings
{
var $id = 0;
var $template = "";
function __construct() {}
}
$page = new Page();
echo $page->page_name;
or you could define the values as constants, if that is what they are
define("PAGE_NAME", "My Page");
you would have access to PAGE_NAME everywhere
I'm not in any way saying this is the right way, it's just a way. :)
I ran into the same issue when I was developing php apps. What I ended up doing was creating classes of static methods and static variables. In essence they work somewhat like namespaces. I am not sure how "standard" this is but it works very well in practice.
The only other option would be to create a singleton like you mentioned in your question, but imho that can be overkill unless you need something like constructors and deconstructors.
Example:
<?php
class MyClass{
private static $my_static_variable;
static public function myStaticMethod(){
return self::$my_static_variable;
}
}
You can then use this anywhere without the need to use global:
function foo(){
MyClass::myStaticMethod();
}
class Bar{
public function myBarMethod(){
MyClass::myStaticMethod();
}
}
I have been considering the same thing myself, and the only conclusion I could come to way to crack open an MVC framework and see how it's built.
The other thing is as mentioned, to start with a single super class and inherit down from there.
So have a class Object, then inherit that into something and so on and so on.

Methods defined outside class?

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.

Categories