Discuss [5.4a1!!!] Traits Syntax in the PHP Development forum on Dev Shed. [5.4a1!!!] Traits Syntax PHP Development forum discussing coding practices, tips on PHP, and other PHP-related topics. PHP is an open source scripting language that has taken the web development industry by storm.
Posts: 3,418
Time spent in forums: 3 Weeks 5 Days 10 h 10 m 53 sec
Reputation Power: 3835
[5.4a1!!!] Traits Syntax
PHP 5.4a1 was released a couple of weeks ago and looks really good, especially with the removal of some legacy features.
One really interesting feature is traits.
Unfortunately, I've not yet been able to get an installation up and running yet
So, has anyone got an installation of 5.4a1 up and running? and can anyone tell me if the traits syntax is as described here https://wiki.php.net/rfc/traits?
Posts: 12,690
Time spent in forums: 5 Months 1 Week 4 Days 3 h 43 m 47 sec
Reputation Power: 8969
It doesn't seem fully supported (at least not the Win32 build of rev. 313197).
- No "instead" (Conflict Resolution)
- No visibility overriding in the derived class (Visibility)
- No aliasing or renaming of specific methods (Aliasing vs. Renaming)
Everything else works.
PHP Code:
<?php
trait Ability {
public abstract function getName();
}
trait Burnable {
use Ability;
public function burn() { echo "Burned this ", $this->getName(), "\n"; }
}
trait Cutable {
use Ability;
public function cut() { echo "Cut this ", $this->getName(), "\n"; }
}
class Forest {
use Burnable;
public function getName() { return "Forest"; }
}
class Paper {
use Burnable, Cutable;
public function getName() { return "Paper"; }
}
$objects = array(
new Forest(),
new Paper()
);
foreach ($objects as $o) {
// downside to resolving traits at compile-time: no inheritance
//if ($o instanceof Burnable) $o->burn();
//if ($o instanceof Cutable) $o->cut();
}
// one alternative is, of course, reflection
function instanceof_trait($o, $trait) {
$rc = new ReflectionClass($o);
return in_array($trait, $rc->getTraitNames());
}
foreach ($objects as $o) {
if (instanceof_trait($o, Burnable)) $o->burn();
// magic? nope.
error_reporting(E_ALL);
if (instanceof_trait($o, Cutable)) $o->cut();
error_reporting(E_ALL & ~E_NOTICE);
}
/*
Burned this Forest
Notice: Use of undefined constant Cutable - assumed 'Cutable'...
Burned this Paper
Notice: Use of undefined constant Cutable - assumed 'Cutable'...
Cut this Paper
*/
// but a better way would be to use interfaces
interface IBurnable {
public function burn();
}
interface ICutable {
public function cut();
}
class Wire implements ICutable {
use Cutable;
public function getName() { return "Wire"; }
}
class Wood implements IBurnable, ICutable {
use Burnable, Cutable;
public function getName() { return "Wood"; }
}
// note that you cannot put interfaces on traits
// with interfaces you can use IBurnable/ICutable as normal interfaces,
// then Burnable/Cutable as "default" implementations
$objects[] = new Wire();
$objects[] = new Wood();
foreach ($objects as $o) {
if ($o instanceof IBurnable) $o->burn();
if ($o instanceof ICutable) $o->cut();
}
/*
Cut this Wire
Burned this Wood
Cut this Wood
*/
// (remember that the first two objects didn't use the IBurnable/ICutable interfaces)
?>
And a more realistic example:
PHP Code:
<?php
interface IIdentifiable {
public function getID();
}
trait TIdentifiable {
private $id = null;
public function getID() { return $this->id; }
}
class User implements IIdentifiable {
use TIdentifiable;
public function __construct($id) {
$this->id = $id;
}
}
$u = new User(123);
echo $u->getID(); // 123
?>
If you're wondering about the whole "private $id" thing and how User can access it, remember one important note about traits: they are not classes by themselves. They're class fragments, and PHP will transparently merge it into a destination class. In effect, User is defined with a private $id and public getID() - the fact that it used a trait to do so has absolutely no bearing on anything.
Posts: 5,654
Time spent in forums: 2 Months 2 Weeks 2 Days 5 h 1 m 44 sec
Reputation Power: 3436
Didn't even know a new version was out. I went ahead and made a throw-away vps to test it out on. Not a whole lot of free time so I only installed a basic php, no db or web server or non-standard extensions.
Not quite sure where i'd use this, but could be interesting.
If anyone wants to mess with it, I setup an ssh login people can use
host: l2.aoeex.com
user: dshed
pass: php54alpha
PING and SMTP packets are blocked by the firewall, no being bad allowed.
Posts: 5,654
Time spent in forums: 2 Months 2 Weeks 2 Days 5 h 1 m 44 sec
Reputation Power: 3436
Quote:
Originally Posted by requinix
Maybe you want to keep the login details out of the post and let people PM you for them?
I figure it's throw away, so not that concerned about it. I have absolutely nothing on there worth any value. I setup the firewall to prevent people using it for spam/flood hopefully.
I'll probably monitor for anything funky, take it down after a few days
Posts: 3,418
Time spent in forums: 3 Weeks 5 Days 10 h 10 m 53 sec
Reputation Power: 3835
Fantastic news
I'm fed up with boiler plating my php classes and see traits as the big work around for this.
One thing I will be very interested in is if/how traits can be auto loaded
will try again at getting an installation sorted out for myself
Kicken - thanks for the SSH info, but couldn't find where to put any test files - didn't even look like there was a web server on it. Maybe I mis-understood what you were making available, maybe someone trashed it before I got there, maybe I just don't know enough about linux/ubuntu to find what I was looking for
Posts: 5,654
Time spent in forums: 2 Months 2 Weeks 2 Days 5 h 1 m 44 sec
Reputation Power: 3436
Quote:
Originally Posted by Northie
Kicken - thanks for the SSH info, but couldn't find where to put any test files - didn't even look like there was a web server on it. Maybe I mis-understood what you were making available, maybe someone trashed it before I got there, maybe I just don't know enough about linux/ubuntu to find what I was looking for
I didn't have time to setup a full lamp environment when I built it quick, so I just compiled a basic php.
You can just store the files in the home directory, anywhere is fine, then use the php cli executable to run them. When I get a spare moment I will try and install apache. Going to be traveling today, so maybe on the first layover if the airport has wifi.
Posts: 5,654
Time spent in forums: 2 Months 2 Weeks 2 Days 5 h 1 m 44 sec
Reputation Power: 3436
Update: I installed apache on the box. I created a folder called 'public' which serves as the document root. Site can be accessed through http://l2.aoeex.com/
Fatal error: Cannot instantiate trait Singleton in /home/dshed/public/northie/index.php on line 11
It appears that the use of __CLASS__ within a trait does not, at present, give the name of the class that calls the trait, but instead has the name of the trait
As it seems that traits are supposed to be a programmatic replacement for copy-and-paste, then I would expect __CLASS__ to have the name of the calling class and __TRAIT__ to give the name of the trait
Have I missed something, or would you agree with me?
EDIT
===================
using a bit of reverse engineering I've got this, which works as expected
Posts: 5,654
Time spent in forums: 2 Months 2 Weeks 2 Days 5 h 1 m 44 sec
Reputation Power: 3436
Quote:
Originally Posted by Northie
As it seems that traits are supposed to be a programmatic replacement for copy-and-paste, then I would expect __CLASS__ to have the name of the calling class and __TRAIT__ to give the name of the trait
I agree, it would be nice to have the separate constants like that.
Posts: 12,690
Time spent in forums: 5 Months 1 Week 4 Days 3 h 43 m 47 sec
Reputation Power: 8969
__CLASS__ is a compile-time constant (has a special token and everything) and is always the value of the class it was used in. Thus Singleton and not Test.
Mysql databases can be setup using the mysql cli tool via SSH. You can create and fully control any database which has a 'dshed' prefix. User/pass for the mysql instance is the same as ssh.
Posts: 5,654
Time spent in forums: 2 Months 2 Weeks 2 Days 5 h 1 m 44 sec
Reputation Power: 3436
So I did a little browsing around the wiki and other stuff to find out what is in store of 5.4 (and beyond). A few interesting things.
A few other things I noticed which are already implemented.
- File upload progress bars are now possible using sessions. Seems a bit complicated, and appears to require session.auto_start=1 in the ini file. It does work in the latest alpha though. http://l2.aoeex.com/kicken/upl/
- Array callbacks can be called directly (no need for call_user_func). ie, $arr=array($obj, 'method'); $arr(1, 2, 3);
- Returned arrays can be used without needing a temp variable. ie, $first = explode(' ', 'this is a string')[0];
And a few things that might make it into 5.4, or perhaps later.
- There is an RFC to make <?= always available, no longer depends on short_open_tags.
- There's an RFC to allow easy object-oriented session handling by extending the SessionHandler class. Not sure if this will make it in this round, would be nice.
And here's a few things on the table, but no decission yet, which I like or find interesting
- array/object literal syntax (json like)
- Autoboxing, automatically convert primitives to an object allowing chain method calling (ie, like jquery) support.
- Various PDO improvements (ie, IN clause handling, better emulation, better consistency)
- __toString like support for other data types. Being able to cast to an int or bool, etc.
- extended type hinting
- conversion of errors to exceptions