Namespace with alias on Yii2 different from directory structure - namespaces

I made a bunch of classes and put them inside the directory common/a/b/c.
So, inside file
Class1.class.php
I have:
<?php
namespace x\y\b\c;
class Class1
...
Namespace is different from the directory structure organization, because I wanted that way. (x\y should map to common/a directory)
On my common/config/bootstrap.php I tried this:
Yii::setAlias('common', dirname(__DIR__));
Yii::setAlias('x/y', '#common/a');
And tried importing this class in another file using
use x\y\b\c\Class1;
With no success. But if I use:
Yii::$classMap['x\y\b\c\Class1'] = __DIR__ . '/../../common/a/b/c/Class1.class.php';
instead of setAlias, it works.
I wonder if it's possible to have namespace different from the directory structure without using composer and how can I do this instead of mapping every class inside common/a/b/c

In bootstrap.php.
Yii::setAlias('common', dirname(__DIR__));
Yii::setAlias('x/y', dirname(__DIR__).'/models');
Inside my "models" folder, there is folder "b" and folder "c" is inside folder "b".
models > b > c
I have a model file named "LoginForm.php" and resides in folder "c".
At the top of this file are these few lines.
namespace x\y\b\c;
use Yii;
use yii\base\Model;
class LoginForm extends Model
Inside my SiteController I have this.
use x\y\b\c\LoginForm;
In one of the action function, i can successfully call this model.
$model = new LoginForm();

Related

How to add own namespace in Yii2

I have changed Yii2 advanced directory structure like following(it's working well):
app-folder
-admin
-assets
-.htaccess
-index.php
-assets
-protected
-backend
...
-common
...
-frontend
...
...
-uploads
...
Now, I am trying to add a namespace as namespace protected\base; into protected/base/AnyFile.php file and use it in a controller as use protected\base\AnyFile;. But, my project is giving error:
syntax error, unexpected 'protected' (T_PROTECTED), expecting identifier (T_STRING) or function (T_FUNCTION) or const (T_CONST) or \\ (T_NS_SEPARATOR)
I saw this issue on the website: Yii2 Custom / Shorter Namespace. However, It didn't work on my condition.
First of all protected is reserved keyword (token T_PROTECTED). You can keep direcory name but you need to change namespace root alias.
In your alias config file protected/common/bootstrap.php write:
Yii::setAlias('app', dirname(dirname(__DIR__))); // set path to protected directory
And then use namespace app\base; and use app\base\AnyFile;.
See Class Autoloading section of the guide https://www.yiiframework.com/doc/guide/2.0/en/concept-autoloading

Get directory path in PhpStorm Live Template

I'm trying to generate a namespace through PhpStorm's templating system (File and Code Templates), I can't see any helpers / means of getting this through PhpStorm's documentation.
I was wondering if there was a way to automatically define the namespace based on the directory:
<?php
// I'm wanting to apply to $namespace
namespace $namespace;
class ${NAME} implements
\Zend\Mail\Mailable
{
/** \Zend\Mail\Factory */
private $factory;
...
}#set( $factory = "factory" ) #set( $this- = "this-" ) #set( $directory = ?)
If my directory/filename is zend/mail/model/notice/send.php I'd like this to generate a namespace of Zend\Mail\Model\Notice; I can get the class name through the ${NAME} variable.
I'm aware I can have the template request the namespace through a dialog when the file is being created, however I was wondering if it's possible to automate this?
if you want , you can use groovyScript.
for example, you can create a variable $FOLDER_OF_FILE$ and set this groovyScript to take the folder of file.
groovyScript("String[] p=_editor.getVirtualFile().getPath().split('/');String prevLast = p[p.length-2];")
you can change and adapt my example for your needs
There are no predefined variables for file path, please vote for IDEA-136387 to be notified on any progress with this feature.

Razor view engine location order not honored?

I created a RazorViewEngine subclass to redefine where it looks for views.
I set PartialViewLocationFormats string array to contain values
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/Partial/{0}.cshtml",
"~/Views/Shared/{0}.cshtml",
The first and last are there by default. The 2nd one is the one I added, so that I could have a "Partial" subfolder in each "Views/ControllerName" folder for partial views used only by views within that controller, rather than adding them to the "Views/Shared" folder.
The issue I'm encountering is that calling #Html.Partial("_TopNavbar") is finding and rendering the '_TopNavbar.cshtml" file that's in the "Views/Shared" folder, rather than in the one under my DashBoards's "Views/Dashboard/Partial" folder.
In other words, there are two different files named "_TopNavbar.cshtml" in two different folders, and I'm expecting it to be found in one location because it's more specific and occurs first in the array, but it's not working that way for some reason I don't understand.
The Partial call is inside "Views/Dashboard/Index.cshtml', and I'm accessing it by directly navigating to "localhost:port/Dashboard/Index", so I'm sure the controller and action are correct.
I have had success using a subclassed RazorViewEngine that only looks for C# views. I extended it to look in a specific controller folder for partials.
Using the CustomRazorViewEngine below and requesting /Home/Index which is calling Html.Partial("_SomePartial") inside it's view will look for partials in this order:
/Views/Home/Partials/_SomePartial.cshtml
/Views/Home/_SomePartial.cshtml
/Views/Shared/_SomePartial.cshtml
This is indeed returning the the partial views in the correct order.
public class CustomRazorViewEngine : RazorViewEngine
{
public CustomRazorViewEngine()
{
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};
MasterLocationFormats = ViewLocationFormats;
PartialViewLocationFormats = new[]
{
"~/Views/{1}/Partials/{0}.cshtml",
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};
}
}
Make sure that you are only using your subclassed view engine by clearing all existing and adding your new custom view engine.
Global.asax.cs
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomRazorViewEngine());

Is 'namespace export ' necessary in TCL?

Is 'namespace export ... ' necessary, in order to use the variable/procs of that namespace in a different namespace using the 'namespace import *' command.
Should we really do the 'export' in the source namespace and 'import'in the destination namespace.
All namespace export does is make commands available for namespace import and prompts them to appear in a simple-mode namespace ensemble (though you've got other options for that). If you don't want to support namespace import, you don't have to; just never export anything.
You invoke commands in another namespace using the fully-qualified syntax:
::the::other::namespace::command "some argument, as normal"
You can also use partial namespace names; that's pretty common as a leading :: is a bit ugly...
In general, I don't want to do namespace import/export: I want the variables/procs to stay where they are. Importing might pollute the destination namespace, which is against the namespace's design.

getDefinitionByName not finding a variable that exists

I am using flash.utils.getDefinitionByName in an attempt to grab an art asset. I use this function quite a bit and haven't had trouble until now. Check it:
assetName = Assets.MegaBerry; // works
assetName = getDefinitionByName("Assets.MegaBerry") as Class; // doesn't work
What the heck?? Error response for the second line is "Variable not found."
If it matters: Assets is a file in my root source directory (it has no package; Assets is the fully qualified name) and I've tried putting:
import Assets;
at the top with no luck.
For reference, in Assets.as I have:
[Embed(source = "../art/Inventory/MegaBerry.png")]
public static var MegaBerry:Class;
Your problem is that embedding the resource into the Assets class will create a static variable of type Class that belongs to that class - which is what you are referencing when you use Assets.MegaBerry: A variable(!) of type Class.
It does not, however, register the MegaBerry class to a fully qualified class name. To do this, you have to use - who would have guessed it - registerClassAlias at some point in your application:
registerClassAlias("Assets.MegaBerry", Assets.MegaBerry);
After that, it will be available everywhere else when calling getDefinitionByName.
** EDIT **
Well that's some unexpected behavior... It turns out, the class that was embedded is in fact automatically registered, but under {className}_{variableName}, instead of the notation you would expect. So using:
getDefinitionByName("Assets_MegaBerry") as Class;
should to the trick.
registerClassAlias also works, but then you need to call getClassByAliasinstead of getDefinitionByName. Sorry for the mix-up.
** END EDIT **
You can also use the Embed tag to inject the resource into a separate class file, which you can then reference as expected by using getDefinitionByName, or simply using an import:
package assets {
[Embed(source="../art/Inventory/MegaBerry.png"]
public class MegaBerry extends BitmapData {
}
}
Instead of calling
assetName = getDefinitionByName("Assets.MegaBerry") as Class;
, instead just use:
assetName = Assets["MegaBerry"];
try:
[Embed(source = "../art/Inventory/MegaBerry.png" , symbol="MegaBerry")]
public static var MegaBerry:Class;
In actionscript, objects actually have a name property that is different from the actual variable name as it shows in code.
For example, if you create a variable as follows,
var myBerry = new MegaBerry();
Then getDefinitionByName("myBerry") will return null.
Only when you set the name of the variable by writing myBerry.name = "myBerry", will getDefinitionByName("myBerry") return what you want it to. The name of the object doesn't necessarily have to be equal to the variable name in code.
In your specific case, I don't think you need to use any of that anyways. Have you tried assetName = new MegaBerry() ?
If you want to find out what the fully qualified name of you class really is, you may do the following:
trace(getQualifiedClassName(Assets.MegaBerry));
You may do that from inside Assets.as, for instance.
You can feed that string back to getDefinitionByName() and get a reference to the class.
trace(getDefinitionByName(getQualifiedClassName(SomeClass)));
// output [class SomeClass]
And remember, getDefinitionByName() only gets you references for classes that are in the same scope as the getDefinitionByName call itself. So, if you are loading external SWFs, getting class references will depend on the application domain you are using and the place, where this code executes.