I understand that by definition, a trait cannot extend a class, however I'm wondering if there's some kind of workaround.
My situation:
I created the package revisionable, which in its first incarnation was a class that you extended from your model which itself extended Laravels base Eloquent class, however over time there were plenty of requests to change this into a trait, so people could use revisionable, and be able to extend their own base class.
Currently, the only that I can think to allow for both an extendable class, and a trait, is to offer both as a whole files, which means I'm repeating the entire code in two files which could easily lead to trouble down the road.
I'm wondering if anybody knows of some solution where I can have one file that is god, and the other file relies on it.
Rules
The existing class cannot use a trait, as existing users of the package on php 5.3 will not have access to traits.
There's absolutely no way to accomplish what you want.
Since Laravel itself (in 4.2) has now abandoned PHP 5.3, it's time to move on too.
Tag a new release that drops the class, add a PHP 5.4 requirement to your composer.josn file, and add this information to your docs.
Anyone still stuck on 5.3 can always just composer require your previous version.
Php 5.3 is a problem.
Back in when it was popular, the programming style was all about include/require files into another files. If you can split your functionality into functions that may be included in trait and in class - it may be a solution. But it depends of the functionality.
Modern way would be decoupling and dependency injections, in other words think units and unittesting.
Problem of a trait as well as the problem of the child-class is that you cannot unittest the pure functionality of what you have done without touching the parent class functionality. You cannot mock parent class, you can only mock injected class, right?
Think modern. Create a class, inject Eloquent object there. And then use this class in traits and some parent class for laravel models.
And forgive Taylor for the fact that you cannot mock the Eloquent. He may be able to fix it in new versions of Laravel. But you'll have to move to PHP7 because it is a requirement for latest laravel releases.
Related
I have some issues regarding the zf2 to zf3 migration of my application. I've gone through the migration guides and started the migration process as describe there.
According to the migration guide, there is no serviceLocator available into controllers anymore. And I used to use it within each and every controller action to inject the config variable array (located in module.config.php), Doctrine MongoDB DocumentManager and the Doctrine EntityManager into the Models where they are needed. Now I'm getting so many deprecated warnings messages as below;
PHP Deprecated: Usage of
Zend\ServiceManager\ServiceManager::getServiceLocator is deprecated
since v3.0.0; please use the container passed to the factory instead
in
/var/www/html/LeapX/vendor/zendframework/zend-servicemanager/src/ServiceManager.php
on line 169
Since I need to access config variables and inject the Doctrine DocumentManager and Doctrine EntityManager into my Models, I had to call $this->getServiceLocator() within my controllers. Let me know how to fix this issue. Is there any possibility to directly inject these dependencies into my Model classes? Should I need to use factories for Models?
And the other question is when it comes to factories regarding the controllers, Should I need to create individual factory for each and every controller of my application? There are quite a lot of number of controllers spread within few Modules in the application. If I add dedicated factory for each and every controller there will be double the number. Let me know the best way to do this.
From what i have read myself, it is no longer possible to call getServiceLocator() from controllers, they removed it since it promotes antipattern.
Here's a blog post from Matthew himself on this issue:
https://mwop.net/blog/2016-04-26-on-locators.html
Another explanation from the guy himself here (shorter, might be easier to digest):
https://github.com/zendframework/zend-mvc/issues/89
I am currently also in the process of trying to migrate a ZF2 (2.4.10) project to ZF3 and face the same issue.
I personally agree with the recommendation to explicitly define dependencies of your classes and controllers instead of (over)using getServiceLocator() method, though depending on your code, refactoring lots of code for this purpose might seem to be a PITA.
Alternatively, this can probably help (though, i can't say for sure since i haven't tried this myself):
http://circlical.com/blog/2016/3/9/preparing-for-zend-f
Let's imagine an OOP framework. There are classes according to database model. And there are some generic classes, which cannot be linked to model - totally written by me, they are doing some calculations, etc. They can't even be static classes - there must be one instance, in some cases (so not everytime). And I don't want to create them everytime I plan to use.
This is when I need to think of singleton - create that object when it's touched, and only once. But they say singleton is not good. Factory?
Disclaimer: I know nothing about singleton classes, first time i hear of them and i just read their description on StackOverflow.
You have autoloading available, why not using it?
I believe this is the right solution. It won't mess your current code and it's an easy solutions (easy is always good). What i'd do is to create an additional folder (or use an existing lib folder if the framework provides it) and set autoloading on it, then just work with classes - static and not -.
Hope it helps!
I’m fairly new to CodeIgniter and have a question. I’m a bit confused about Classes, Libraries and Objects.
Does CodeIgniter replace the normal PHP way of usings objects i.e. $var = new car(); with libraries i.e. $this->load->library('some_library'); $this->some_library->some_function(); ?
If both are valid, is there a difference? If so, what are the differences and when do I use one over the other? Which is more common/proper?
I am asking because I created a class, but I'm not certain what is the correct manner in which to instantiate it.
Thanks in advance
I am not familiar with CodeIgnitier. But familiar with other PHP frameworks. Most of frameworks use this way for performance improvements, registering things, executing certain events, and making things simpler for developer...
For example if you want to create class "car" with is somewhere in library directory you would have to include the file first before you can create object of that class (miltiple lines of code, more room for error). The framework will create the class and includes related files in 1 line of code (easier and safer).
Framework way also works as a factory. Instead of recreating an object, it will create object only once and every time you call the method again it will return the reference to existing object.
More things are happening behind the scenes when you use framework. Things are getting registered, etc...
CI doesn't replace class behavior per se, it simply adds functionality that allows access to custom libraries/models/views as singleton objects via the core object for simplicity.
Nothing is stopping you from creating (as I have in one of my projects) additional files with classes for non-singleton entities and require them in a model for further use. On hindsight, I should probably have used helpers for this.
What the loader ($this->load) class does, among other things, is it creates a single object of the specified class (model, library or view - not helpers though, see below) and attaches it as a property of the core class that is normally accessible via $this.
Helpers are a bit different. They are not attached, but instead simply 'read' into the global namespace from the point where they are loaded.
To answer your question, it would be more proper to use the loader class in instances where you don't need more than one instance of a class created. If you need 'entity' classes, your best CI-compliant bet would be to create them as helpers.
Given only this context, this looks like Inversion of Control (maybe I'm wrong, I haven't looked too closely at CodeIgniter).
You don't want to rely on the type car as in new car(). What if later you want to make $var a racecar? $var can still do the same things, but it is forced to be a car because you constructed it directly. Or what if you are testing this class, but car is some complex object which calls some external service. You want to test your logic, but don't care if the car service isn't working. So you should be able to change $var to actually load a mockcar. You can't do that if you do $var = new car().
What is Inversion of Control?
Suppose you are building a web application that is going to be a packaged product one day, one that users will want to be able to extend and customize.
It comes with a core library consisting of PHP files containing classes:
/library/
/library/frontend.class.php
/library/filesystem.class.php
/library/backend.class.php
Now, suppose you want to keep a clean core that users can't patch. Still, you want the user to be able to customize every nut and bolt if need be.
My current idea is to create an autoloading mechanism that, when a class is instantiated, first loads the core include:
/library/frontend.class.php
then, it switches to the user directory and looks whether there is an include of the same name:
/user/library/frontend.class.php
if one exists, it includes that as well.
Obviously, the user include must contain a class definition that extends the definition in the core include.
Now my question is, how would I instantiate such a class? After all, I can always be sure there is a definition of:
class frontend_core
but I can not be sure there is a
class frontend_user extends frontend_core
However, I would like to be able to rely on, and instantiate, one class name, regardless of whether there was a custom extension to the class or not.
Is there a clever way, idea, or pattern how to achieve this?
Of course, I could write a simple factory helper function that looks for the user class first and then for the core class and returns an initialized object, but I would really like to keep this as clean and simple as possible, because as I said, it is going to be a packaged product.
I am looking for a smart trick or pattern that uses as little code, and introduces as little new functionality, as possible.
Why don't you follow the approach as used by Propel? You generate your base classes and already provide an empty User class (extending the base class) where your users can put their overrides/specific implementation details, and in your code you always refer to the User classes. So basically you just use the inverse of the logic you described.
If the explanation above isn't clear, check out http://propel.phpdb.org/trac/wiki/Users/Documentation/1.4/QuickStart#a6.UsingtheGeneratedSQLandOMFiles and generate code for a small database. The base classes are in the om folder, the (by default empty) user classes are in the root folder.
I would implement hooks in the core, so users dont have to hack the core, but are still able to extend the core using hooks
I'd go with using the constructor of the core class to determine the user class to load, and then implement a factory method in the core class to generate instances of the user class. By making the constructor of the user class protected, and having the user class extend the core class you can be sure that code elsewhere cannot instantiate the user class.
C.
I think it's more complicated with a single filename when you want to use inheritance as well. Basically class user_frontend extends core_frontend has to know where to find both classes. Both must be included.
If you just want to do new Frontend you could use PHP5.3's class_alias to point Frontend to the main class to use. Below 5.3. you could use a ServiceFinder, that knows how to map Service Names to Classes and then get the Frontend with $service->get('frontend') or use a Dependency Injection framework.
Edit I removed the Loader code given before, because it was suffering from exactly this problem.
You could have a loader class that will decide which class to instance:
Loader::instance()->load('Frontend')
Does anyone know if it is possible to specify an interface for a Doctrine model to implement within YAML?
I cannot find anything within the documentation.
Thanks
I don't believe there is a way to do that. However, you can implement an interface in you model by extending the doctrine-generated model, and implementing the interface in the subclass. In my opinion, no value is lost by having to do this extra step, because once you declare you are implementing an interface, you have to actually enter the code to do so.
You are better off implementing the interface in a subclass of the generated class, so that if you re-generate the class, none of your changes are lost.