I came across two limitations.

1) If two traits defined allowed_actions with different values, a Fatal Error is thrown because the two arrays do not have the same value. Trait1 and Trait2 define the same property ($allowed_actions) in the composition of (my controller). However, the definition differs and is considered incompatible.

2) SilverStripe has an allowedActions method. If two traits define this, you get a Fatal Error Trait method allowedActions has not been applied, because there are collisions with other trait methods (edited)

people have been wanting traits over dataextensions

It is just a thought experiment. I thought it might be useful to replace DataExtension with a native PHP feature someday 🙂

The methods do get added, the trick is getting SilverStripe to recognize them as whitelisted actions. I did sort-of get it to work by defining the allowed_actions in YML but that's cheating a bit 🙂

Yes, I tried a couple of things, namely defining allowed_actions on both traits and attempting to defined allowedActions($limitClass = null) on each trait:

  1. <?php
  2. use SilverStripe\Control\Controller;
  3. use SilverStripe\Security\Security;
  4.  
  5. class UserController extends Controller
  6. {
  7. use CurrentUserActionTrait;
  8. use ViewUserActionTrait;
  9. private $member = null;
  10.  
  11. public function init()
  12. {
  13. parent::init();
  14. $this->member = Security::getCurrentUser();
  15. $this->response->addHeader('Content-Type', 'application/json');
  16. }
  17.  
  18. }
  19.  
  20.  
  21. <?php
  22.  
  23. use SilverStripe\Security\Member;
  24. trait ViewUserActionTrait {
  25.  
  26. public function view($request) {
  27.  
  28. $id = $request->param('ID');
  29. $member = Member::get()->byID($id);
  30. if (!($member && $member->ID)) {
  31. return "{}";
  32. } else {
  33. return json_encode([
  34. "ID" => $member->ID,
  35. "Email" => $member->Email,
  36. "FirstName" => $member->FirstName,
  37. "Surname" => $member->Surname
  38. ]);
  39.  
  40. }
  41. }
  42. }
  43.  
  44.  
  45. <?php
  46.  
  47. trait CurrentUserActionTrait {
  48.  
  49. public function current($request)
  50. {
  51.  
  52. if (!$this->member) {
  53. return "{}";
  54. } else {
  55. return json_encode([
  56. "ID" => $this->member->ID,
  57. "Email" => $this->member->Email,
  58. "FirstName" => $this->member->FirstName,
  59. "Surname" => $this->member->Surname
  60. ]);
  61. }
  62. }
  63.  
  64. }
(edited)

other config settings can be set that way, and when applied things coming from a trait should be indistinguishable from the class itself...

Christmas wish list... being able to add allowed_actions via a trait