I'm using the Warden auth package, and need to add some functionality and relationships to the default Model_User class that ships with the package. The author kindly instructed me to extend the class in APPPATH . 'classes/model/user.php' with something like this:
class Model_User extends \Warden\Model_User {
\\ your extra code
}
However, when I go to access the model, either in a controller or the console, I'm not able to make use of any of the additional code I added. I get a error thrown telling me that the property in question cannot be found for \Warden\Model_User, and the backtrace seems to show no indication that my class extension is being loaded.
Am I missing something?
No, the author of Warden doesn't quite understand how class extensions work, or he does but he didn't access the class correctly.
For a package there are two options.
1) it is self-contained, and in it's own namespace. In this case, you can not extend it unless the author of the package has coded something manually to work around it (i.e. load from global and if not exist load from package).
2. it is added to the core (like for example the Auth package). This means that FuelPHP will alias the classes in the package to the global namespace (like FuelHP does for it's own core classes), which means you can extend the class like you describe (which is how you would extend a core class).
So the question is, does Warden fall in 1) or 2), and in case of 1), was something provided? I guess you'll have to ask the author of the package.
Hi @WanWizard, Warden falls under point 2)
It seems the problem was that he had a namespace in his model and:
1) Hadn't specified the 'model_to' in his relation property
2) The model name was following the Fuel naming conventions ('Model_ModelName')
DParis or AWayne... What did you do to get this working? I am having the same issue. I created the Model_Profile extends \Warden\Model_Profile and added my _properties(), but it is like it's not even there.
Daniel, add your Model_Profile in your APPPATH bootsrap file,
Autoloader::add_classes(array(
// Add classes you want to override here
'Model_Profile' => APPPATH.'classes/model/profile.php',
));
That should not be nessecary for app classes.
I assume (I haven't checked the code) that Warden tries to load the model class from within it's code, without namespacing it. Which means it tries to load it in the \Warden namespace (which is the current namespace at the time of load). Which is were the default class can be found, but not the extended one.
You should modify the Warden code to load using the proper namespace, i.e. prefix it with a \ to force a load from the global namespace, which is where the extension lives, and where the original is aliased to when no extension is present.
Please explain why FuelPHP would do that, if you request \Model_Profile?
If so, we might have a bug in the autoloader. As I don't have it installed, maybe you could add some debugging to the autoloader to see why the wrong class is loaded and/or returned?
Awayne, thank you that worked like a charm.
This is how I was calling it in the controller
$user = new \Warden\Model_User(array(...VALUES HERE...));
$user->profile = new Model_Profile(array(...VALUES HERE...));
It was completely overlooking the APPPATH \Model_Profile and using only the \Warden\Model_Profile. I thought that is what was going on because all errors thrown were exceptions from \Warden\Model_Profile.
@WanWizard i'll do some debugging and post what I find back here @Daniel Yes, I was getting the same exceptions from \Warden\Model_Profile, does extending Model_User bring the same issues?
WanWizard, I checked and found that Autoloader finds both classes but, it seems that autoloader looks for a class in the APPPATH as a last resort (on line 276 in Autoloader), meaning it searches for classes added to the core namespace before it looks for the APPPATH (on line 240) and classes added to the core namespace will usually return true so they're loaded instead of the APPPATH classes.
Current Sequence:
- checks for class in Autoloader::$classes
- then checks for class with Autoloader::find_core_class()
- then checks in Autoloader::$namespaces and Autoloader::$psr_namespaces
- then lastly checks for class in APPPATH
Shouldn't it be in this order:
- check for class in Autoloader::$classes
- then check for class in APPPATH
- then check for class with Autoloader::find_core_class()
- then lastly check in Autoloader::$namespaces and Autoloader::$psr_namespaces
I actually designed the Autoloader to work this way. It is for performance issues. When a package sets it's namespace as a core namespace, it does multiple things:
1. It auto-aliases that namespace to the global space.
2. It bypasses all "auto-finding" for class loading in that namespace.
This means it forces you to add the class in your bootstrap. Again, this is purely for performance. If we changed the order around as suggested, it increases the number of stat calls on the filesystem, which slows it down.
I just want to take a second to say thank you very much to WanWizard, Dan and AWayne for being awesome and responsive. Aside from Fuel being incredible, the support and responsiveness of the development team and contributors and community as a whole make it stand out... Wish there was more I could do to contribute and help out...
Keep up the work and mad kudos to all!