I am playing with the build settings in my build.properties file for propel (version 1.5.4) but don't get it right.
Example: Table News should have
class Model_News in ./Model/News.php
class Model_Base_News in ./Model/Base/News.php
My main problems:
propel adds the project name as a folder between Model and News.php like: /Model/project/News.php
propel adds the propel.classPrefix to the file, too. So propel.classPrefix = Model_ builds class Model_News inside /Model/project/Model_News.php
aaaaaaaaaaaahhhh :-(
I don't think you can customize the paths to this form by only using build.properties. You probably need to overload the OMBuilder::getClassFilePath() (used by PropelOMTask::build()) function in your own custom build classes. Unfortunately you cannot just override the OMBuilder class, but you must create subclasses for all *Builder classes.
Personally, I'd stick with the Propel conventions and just use the Propel autoloader for Propel classes. Not as clean as your intended solution, perhaps, but I'd not reject an ORM just on the basis of its internal file naming.
Related
I need to understand how to load classes in php. I want to access classes methods by instantiate the class only with its name, for example:
$foo = new Foo();
$foo->method();
And not like this:
$foo = new \Class\Bar\Foo();
I'm in a Symfony 2.7 environment.
Thanks in advance!
EDIT
My bad, I should have specified that I'd like to use classes like this in the whole project, not only in a few files.
You should use those classes (i.e. import them) like:
use strrife\MyBundle\Entity as Entity;
...
$e = new Entity();
The official docs can be found here.
PS
If you're using some IDE (for example, PHPStorm which personally I highly recommend), then, when you type Entity and this class wasn't imported yet, it gives you a list of options to import that class from.
EDIT
You shouldn't do that.
Importing the classes like that in the entire project is actually a bad idea because that might cause naming conflicts (and probably will if you'd like to do that for Symfony classes).
As a workaround for your project classes you can add a few lines to composer.json specifying the autoload paths to all your project folders.
You can also:
put all your entities to one single folder (very bad)
or write a custom __autoload() function that would iterate through files and folders searching for your class (docs), but it'd bring the same problems + some performance issues.
But I highly discourage you from doing that because... well, namespaces bring order and structure and you're likely to end up with class redeclarations.
Here is the scenario.
I am implementing namespaces into my projects.
I have my own custom bridge library that calls other libraries like Zend to do the heavy lifting.
I have no problem using fully qualified namespaces in my custom bridge library but would like to keep the code as terse as possible in my controllers, models and view.
Here is an example of some aliasses i would like to use:
use BridgeLibName\Stdlib\Arrays as arr;
use BridgeLibName\Stdlib\Objects as obj;
use BridgeLibName\Stdlib\Strings as str;
use BridgeLibName\Stdlib\Numbers as num;
use BridgeLibName\Stdlib\File as file;
etc.........
Example usage:
$file = new file('path/to/file.txt');
$file->create();
or
$obj = arr::toObject(['key1'=>'value1']);
is it possible in any way to create an alias or constant that can be globally accessible and not discarded at the end of each file?
Some kind of bootstrap file that can make these aliases stick.
As I was writing the question i thought of a solution.
You can fake it by creating classes that extend the namespaced classes.
example:
class arr extends BridgeLibName\Stdlib\Arrays{
}
One important thing to remember:
If you are going to extend the classes the namespaced class will have to be loaded.
This could have performance implications if used too much since aliases and namespaces are only loaded as needed.
Since I am only using it to bridge to other classes there is very little logic inside my bridge files.
These bridge files in turn uses aliases and namespaces correctly thus loading the real files as needed.
I you are not careful with the implementation you can load a lot of unnecessary stuff and cause your app to become slow and bloated.
A nice thing I noticed is that good IDEs like netbeans also seems to be able to do auto completion with this method.
If there is a better way to do this please let me know.
Just thought of an amendment to this method to fix the problem with unnecessary class instantiation.
The core library can work with the normal psr-0 loader.
To have the aliases autoload I created an aditional dir named includes next to my namespaced class.
in composer you describe it like so:
"autoload": {
"psr-0": {
"BridgeLibName\\": "."
},
"classmap": ["include/"]
}
Now your libraries will load as expected from the correct namespace and your alias classes will autoload as needed.
Classes put into the include dir can now extend the namespaced classes ( as shown above ) and will no longer be loaded prior to being used.
Now you have global aliases without having to sacrifice performance by loading unused classes.
Because I am working with legacy tables, I wrote my own Auth_Adapter, named User_Auth_Adapter_DbTable. I have a module user and I want to have this class there.
However, I have no idea where to actually put the file and how to name it so the Zend autoloader can find it. I have googled for more than an hour and did not find a hint, so I put it under /application/modules/user/controller/Auth/Adapter/DbTable.php, because it is used by the controller there. But it is not found.
Can you share some code from adapter? I think logically it must be in models folder. And the name of this class should follow Zend Framework naming conventions. So if you will put it to models/user/auth/adapter/DbTable.php class should be named as Model_User_Auth_Adapter_DbTable
I think you need to define service folder.
Define folder named service path /application/modules/user/service/ (Recomended Zend-project structure), put there your adapter DbTable.php (class name must bee Application_Modules_User_Service_DbTable). You can call this class:
$adapter = new Application_Modules_User_Service_DbTable();
I'm building a library for our CodeIgniter app, but it requires many classes (currently I'm at 12).
Is there a best practice for packaging these many clients into one library. So I can just make one call to load it. i.e:
$this->load->library('soaplibrary');
Thanks!
As Summer points out, they have handled this situation somewhat elegantly in CI 2.0 with the concept of Drivers.
With a Driver, you actually create a subdirectory within your 'libraries' directory that contains your 'super' class, and another directory for 'child' classes. Better visual representation of the structure...
This was taken from Here.
and once you have constructed your library, here is the documentation on how to use it.
In CI 2.0, there are drivers to handle this situation. Good luck!
In CodeIgniter 3.1.9 when you load a library file, all classes in this file are included into code.
Let's say in soaplibrary.php you have
class SoapLibrary {
public function someMethod(...
class Test {
public function anotherMethod(...
In your controller you can do:
$this->load->library('soaplibrary');
//now on you can do
$this->soaplibrary->someMethod();
//but also
$test = new Test();
$test->anotherMethod();
CodeIgniter attempts to call the constructor of class SoapLibrary, hence a class with that name must be in there.
In Codeigniter, when we use $this->load('class_name') in the controller, CI will try to create an instance of the class/model using its constructor.
But sometimes, I don't actually need an instance from that class, I just want to call some static functions from it. Also, there is a big limitation with $this->load('class_name'), it does not allow me to pass parameters to the constructor (unless we extend or modify the core class of CI).
I think the $this->load('class_name') function should only do a require_once on the class php file for me, and let me freely do things (create instance/call static functions) with the class in the controller.
Should I simply ignore this function and use require_once or writing my own __autoload function to load up the classes? This way, I just feel strange because it seems I am not writing codes inside the CI box.
You can pass parameters to your constructor. See the "Passing Parameters When Initializing Your Class" section in the user guide.
I found CodeIgniter's object creation and loading to be very limiting. I want full control over my code, and little magic in the background. I have instead started using Doctrine's Class Loader. It's very lightweight and is essentially SPL autoloading (also a good alternative). You don't need the whole Doctrine shebang with ORM and all that stuff, just the ClassLoader. There's some configuration tinkering to get this right, but it works wonders.
With PHP 5.3 I now have namespaced classes in the Application directory. For instance I created a new class in the Tests directory: Application\Tests\SomeTest.php
That test could look something like this:
namespace Tests;
class SomeTest {
...
}
I would use this class in my code (controllers, views, helpers) by simply using the fully qualified namespace (i.e. $test = new \Tests\SomeTest) or a "use" statement at the top of my code (use \Tests\SomeTest as SomeTest).
In this way I intend to replace all libraries and models with OO namespaced variants. There are many benefits to this: fast autoloading with SPL, full IDE intellisense support for classes/methods (CodeIgniter is really bad for that), your code is more portable to other frameworks or projects.
That said, I still use a lot of the CodeIgniter engine. This basically means I have $CI =& get_instance() in most of my classes. It's still a work in progress and I think the main reason I need CI is for it's database access. If I can factor that out ... and use something like Dependency Injection, then I won't need CodeIgniter in my classes at all. I will simply be using it for it's MVC framework, and using it's methods occasionally in my controllers.
I know this goes above and beyond your question, but hopefully it's some food for though - and it helps me to get it in writing too.