I am trying to extend the DbManager in order to set my own table names for $itemTable, $itemChildTable and $assignmentTable.
Sadly I don't know how to add my new folder of myComponents to the namespace, and I don't want to create it under the same folder as the other in case I need to upgrade the framework.
Anyone added an other folder for namespaces to Yii2.0 ?
It doesn't need to be in the same namespace, as long as you correctly specify the class namespace "path" when you update the configuration.
If you have added the new folder under the common part, the class path for your DbManager would be common\myComponents\DbManager. As said, if then correctly update the config, you should be set.
Related
I found, that in Yii 2 there is an interesting namespace app. For example,
use app\assets\AppAsset;
There http://www.yiiframework.com/doc-2.0/guide-concept-autoloading.html I found info
When using the Basic Project Template, you may put your classes under
the top-level namespace app so that they can be autoloaded by Yii
without the need of defining a new alias. This is because #app is a
predefined alias, and a class name like app\components\MyClass can be
resolved into the class file AppBasePath/components/MyClass.php,
according to the algorithm just described.
Also I found http://www.yiiframework.com/doc-2.0/guide-concept-aliases.html#predefined-aliases
#app, the base path of the currently running application.
And, when I call
print_r(Yii::getAlias("#app"));die;
it's printing
/home/u1326jyq/domains/lifesim.biz/public_html/dev
Am I right or not, that namespace app is equal to /home/u1326jyq/domains/lifesim.biz/public_html/dev ?
But, if I trying to execute script like
use home\u1326jyq\domains\lifesim.biz\public_html\dev\assets\syntaxhighlighter\SyntaxhighlighterAsset;
SyntaxhighlighterAsset::register($this);
it's fails with 500 error.
Where is definition of the app namespace in Yii2 and how to define custom myCustomApp namespace, that will be equal to my path /home/u1326jyq/domains/lifesim.biz/public_html/dev, to using it with code like
use myCustomApp\assets\syntaxhighlighter\SyntaxhighlighterAsset;
that must be equal to code
define('__ROOT__', dirname(dirname(__FILE__)));
require_once(__ROOT__.'/assets/syntaxhighlighter/SyntaxhighlighterAsset');
?
Thank you very much!
I'm a beginner to L5. I read the documentation about extending classes but i didn't find any information about where to put the file in which i extend the class.
**I have to extend Str.php class. I have read that in L4 it had to be done by putting that file under App/folder but i didn't find that folder in L5.
So please can you tell me how can i do that?
This is the information i have now:
First, you must find where the class file is. We will be extending the Str class, which is under vendor/laravel/framework/src/Illuminate/Support. Note that you can also find this class under the aliases key in app/config/ app.php.
Now create a new folder called lib under app/folder. This folder will hold our class extensions. Because the Str class is grouped under the folder Support, it is suggested that you create a new folder named Support under lib too.
Now create a new file named Str.php under app/lib/Support, which you've just created:
But this is for L4
That's more of a general PHP question and there are two parts: 1) How to extend a class and 2) where to put files.
1) Extending classes isn't something Laravel or anyone else provides. That's right there in the language:
class A {}
class B extends A {}
As long as class A exists and is available, then class B can extend from it.
2) Where the files are is also important here. If you're defining class B and want to extend class A, the php runtime needs to know where to find A. Usually class A isn't defined in the same file as class B.
There are many ways to do this. You could require or include class A when you define class B. That would look something like:
a.php
class A {}
b.php
require "a.php";
class B extends A {}
Now with a lot of files like in the Laravel framework or any worthy library, you're going to have a lot of files to include and have to keep track of how to include those files. That's no fun. So, instead of doing that, PHP has provided a way to autoload the classes. That is, if you define classes in a predictable way, PHP can figure out what classes you're talking about without you having to use require or include statements.
There are also many ways of autoloading php files. In Laravel (and many, many other projects), the composer autoloader is used.
This means that files have to be placed in a pre-defined way in order for the composer autoloader to find them. By reading about the composer autoloader and then digging into the code to see how Laravel's classes are autoloaded, you'll be able to figure out how that happens.
Despite the intricate detail of Peter's answer, I figured I'd write something much more concrete: it doesn't matter.
If you check composer.json, you'll see that we are autoloading everything that is placed inside the app directory anyway. Hence, the choice is really yours. All that matters is that you maintain a sensible and readable structure. For example, you could place it in app/Lib, and namespace all your classes App\Lib (if App is your base namespace of course, which can be changed with php artisan app:name). Of course, you could also have a folder like Helpers/Lib for your extended classes, and keep some form of helpers.php with global helper functions in Helpers.
Why would you do this? Well, you might want to have an easy way to call your new Strfunctions, so instead of having to do Str::yourNewMethod($argument) everywhere, you could add a helper function yourMethod($argument) to easier call the function (if you intend to use it extensively).
One thing you have to remember though, as mentioned by Peter, is that the class you are extending won't automagically be found. It will, however, be autoloaded. Hence, to reference it you have to remember to namespace it, such as in the example below.
<?php namespace App\Helpers\Lib
Class Str extends \Illuminate\Support\Str {}
Also remember to namespace correctly when you call your own class.
I have one namespace (for example \App\) that contains all my app encapsulated, currently I'm using composer to autoload this namespace using PSR-0 and checking for two different folders, "Main" and "Client". (Giving priority to the client folder, allowing me to override the main app functionality to meet the client's requests by only creating the necessary override files in the client's folder)
Now, I'm thinking that it would be better if the client's override classes extended the original one, because I realized that the main use for this is to edit only some of the class methods, and I want to future proof the "override class" for new methods that could appear in the "main class". And I've been struggling with a way to make this happen, keeping the namespaces.
Example: Sales Controller Class ==> \App\Controller\Sale
If there isn't a "Client/App/Controller/Sale.php" file it uses the default "Main/App/Controller/Sale.php"
But if there is, what I want is that "Client/App/Controller/Sale.php" could be able to extend "Main/App/Controller/Sale.php"
<?php
namespace App\Controller
use \Main\Controller\Sale as OriginalClass //The Sale class in Main Folder
class Sale extend OriginalClass {...}
This way, I could override only some methods in the client's class and if the main class gets updated it would be reflected in the client's app.
The problem is, that since both, the client and main class are in the \App\ namespace, I can't figure out a way to get the "use" statement above to work. The main reason is that any prepended namespace (in the example "\Main + namespace) that I put in it won’t work, because the file's namespace would be different.
Another way I thought it could work is by tinkering with the composer autoload, and check if the namespace starts with "Main" or maybe "Original", then remove that part from the namespace and force to use the "Main" folder. But I couldn't find where this could be implemented.
Another solution I considered was to subdivide the main class functionality in sub classes, that could be overridden using the current autoload scheme, but I don't know if it is wise to have so many classes and files scattered through the system.
Any help or guidance is always welcome.
No Solution, but a workaround
I ended up separating the clients and main classes namespaces. Then, I made a function that recives a class name and checks if the class exists in the client's folder and prepend the "Client\" namespace, or append the "Main\" namespace before initializing.
So
$class = "Path\\To\\My\\Class";
$class = checkClass($class);
// Now class is either "Client\\Path\\To\\My\\Class; or Main\\Path\\To\\My\\Class;
//Uses:
$object = new $class();
$static = $class::StaticMethod();
Also, the "Client" version of the classes extends their "Main" --base-- class.
Eg: Client\MyClass extends Main\MyClass
composer.json contains the following
...
"autoload": {
...
"psr-0":{"Acme": "app/lib"}
},
at app/lib/Acme/Models/Product/Display.php I have the following:
<?php
namespace Acme\Models\Product;
use Eloquent;
use Db;
class Product_Display extends Eloquent
{
I'm lost on how to call that class given the underscore in the Class Name inside of a repository class:
<?php
namespace Acme\Repositories;
use Acme\Models\Product\Display as Product_Display;
...
Product_Display::where('page_id','=',$page_id)->first();
This gives me a Class 'Acme\Models\Product\Display' not found error.
I'm guessing the problem lies in the use Acme\Models\Product\Display as Product_Display, but I've tried several variations none of which seemed to cure the problem.
Did you composer dump-autoload? Do this by typing composer dump-autoload in the terminal from the root of your project.
Every time you make changes to your composer.json file you need to allow composer to reconstruct the autoload files. In the case of psr-0 this is all you need to do.
In the case of classmap autoloading, every time you add a file to a directory that is being autoloaded, you need to composer dump-autoload.
edit:
To fix: change use Acme\Models\Product\Display as Product_Display; to use Acme\Models\Product\Display. Change the class name from Product_Display to just Display.
I think I spotted the issue. You have use Acme\Models\Product\Display as Product_Display; but you need to use Acme\Models\Product\Product_Display; since the last part of the use statement is the name of the class. In this case your class actually is named Product_Display, not Display (which is the file name). You might also need to change the file name to match the class name (also for conventions sake you should do this).
You are using PSR-0 autoloading. This scheme converts every backslash and every underscore into a directory separator when building the path to the file.
So Acme\Whatever_Underscored is searched for in the path prefix/Acme/Whatever/Underscored.php.
With PSR-4, the rules have changed. First, it only works for namespaced classes, not the old Acme_Underscore_Endless_Classnames. Second, you don't have to have a set of otherwise emtpy directories if you don't want to. Third: Underscores are NOT converted to directory separators.
With PSR-4 rules, the Acme\Whatever_Underscored is searched for in the path prefix/Acme/Whatever_Underscored.php - or even prefix/Whatever_Underscored.php if configured so.
You got confused because you connected the class name in the code with the path to the file. PHP only cares about the class name in use imports. Always use the class name as it is defined in your class's file. Then the autoloader kicks in and tries to find a matching file - with the rules of either PSR-0 or PSR-4. If it cannot find the correct file (either the path does not point to the file correctly, or the file does not contain the class being searched for), you get an error.
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();