I need to know a module name for a particular model, if I know only model's name.
For example, I have:
model Branch, stored in protected/modules/office/models/branch.php and
model BranchType stored in protected/modules/config/models/branchtype.php.
I want to know the module name of branch.php from the class of branchtype.php.
How to do this?
Unfortunately Yii does not provide any native method to determine the module name that model belongs to. You have to write your own algorithm to do this task.
I can suppose you two possible methods:
Store configuration for module's models in the module class.
Provide the name of your model using path aliases
First method:
MyModule.php:
class MyModule extends CWebModule
{
public $branchType = 'someType';
}
Branch.php
class Branch extends CActiveRecord
{
public function init() // Or somewhere else
{
$this->type = Yii::app()->getModule('my')->branchType;
}
}
In configuration:
'modules' =>
'my' => array(
'branchType' => 'otherType',
)
Second method:
In configuration:
'components' => array(
'modelConfigurator' => array(
'models' => array(
'my.models.Branch' => array(
'type' => 'someBranch'
),
),
),
)
You should write component ModelConfigurator that will store this configuration or maybe parse it in some way. Then you can do something like this:
BaseModel.php:
class BaseModel extends CActiveRecord
{
public $modelAlias;
public function init()
{
Yii::app()->modelConfigurator->configure($this, $this->modelAlias);
}
}
Branch.php:
class Branch extends BaseModel
{
public $modelAlias = 'my.models.Branch';
// Other code
}
Try this:
Yii::app()->controller->module->id.
Or inside a controller:
$this->module->id
in Yii2 try this:
echo Yii::$app->controller->module->id;
for more information see Get the current controller name, action, module
Related
I tried all the options. Still, it is showing "Constant expression contains invalid operations". I am using Laravel 5.5, Please Help. I need to define table name in constant and use it in Model.
I wrote in Model:
protected $table = Config::get('constants.dbTable.EMAILTEMPLATE');
And In constant.php inside Config:
return [ 'langs' =>
[
'es' => 'www.domain.es',
'en' => 'www.domain.us' // etc
],
'siteTitle' => 'HD Site',
'pagination' => 5,
'tagLine' => 'Do the best',
'dbTable'=>[
'EMAILTEMPLATE' => 'stmd_emailTemplate'
]
];
I want to use emailTemplate table.
Based on the code you have posted in the comment, you are trying to assign a value into a property in your model but you are assigning it too early (assumed from the keyword protected.) You can't do this:
class SomeModel extends Model
{
protected $someProperty = config('some.value'); // Too early!
}
because you are trying to initialize a property that requires a run-time interpretation.
There's a workaround; use your constructor.
class SomeModel extends Model
{
protected $someProperty; // Define only...
public function __construct() {
parent::__construct(); // Don't forget this, you'll never know what's being done in the constructor of the parent class you extended
$this->someProperty = config('some.value');
}
}
I have a controller in components/test/test/controllers folder, called MyController. If I set the namespace as "namespace app\components\test\test", and then I try to call the controller if says "Page Not Found".
I have been reading and I know that by default Yii2 sets namespace for controllers to "app\controllers".
Also know that you can change namespace for all controllers from config:
'controllerNamespace' => 'app\\components\test...'
But I just wanted to change for one controller not for all. Something similar to modules, there you can do:
$this->controllerNamespace = 'app\modules\test\test';
I just found there is something called "controllerMap", maybe this could be a solution? any ideas?
Example
I have created inside "components" (basic template) a controller LocationController with this content:
namespace app\components;
use yii\web\Controller;
class LocationController extends Controller {
public function actionAdd() {
return "hola1";
}
public function actionRemove() {
return "hola2";
}
}
When I created a link Yii::$app->urlManager->createAbsoluteUrl("location/add"); and click on it I get "Page not found" error.
UPDATE
I have found that is possible to add classes to classMap, but not sure where to place it:
Yii::$classMap['app\components\LocationController'] = '..path.../components/LocaitonController.php'
Maybe this could do the trick?
About your "Not found" problem, your controllerNamespace and namespace must have the full path of the controller, in your case:
app\modules\test\test\controllers
Now,to change the path for a single controller I can only think of creating a Module inside your app (like you mentioned):
<?php
namespace app\modules\test\test;
/**
* module definition class
*/
class Module extends \yii\base\Module
{
/**
* #inheritdoc
*/
public $controllerNamespace = 'app\modules\test\test\controllers';
/**
* #inheritdoc
*/
public function init()
{
parent::init();
// custom initialization code goes here
}
}
And add in your config the module:
$config = [
...
'modules' => [
'module' => 'app\modules\test\test\Module'
]
];
EDIT
You can also add in your config:
$config = [
...
'controllerMap' => [
'location' => 'app\components\LocationController',
],
];
I want to extend, for example, Zend\View\Helper\HeadMeta with my own class and I create a factory for it and call it by
public function getViewHelperConfig()
{
return array(
'factories' => array(
'MyHeadMeta' => __NAMESPACE__ . '\View\Helper\Service\MyHeadMetaService',
),
);
}
from Module.php, but I have
$this->view
is null in MyHeadMeta class if I call it by
$this->MyHeadMeta()->setCharset('utf-8');
in my view file.
How do I instantiate my view helper properly?
UPDATE
My class looks something like this:
MyHeadMeta.php
use Zend\View\Helper\HeadMeta;
class MyHeadMeta extends HeadMeta
{
//
}
UPDATE 2
MyHeadMetaService.php
class MyHeadMetaService implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$viewHelper = new MyHeadMeta();
// some settings to set...
return $viewHelper;
}
}
If you only extend the existing HeadMeta class then you should register it as an invokable as is done with the original HeadMeta view helper in the HelperPluginManager.
So change your config like this:
return array(
'invokables' => array(
'MyHeadMeta' => 'View\Helper\Service\MyHeadMetaService'
)
);
By the way I don't think it is necessary to use the full path with __NAMESPACE__. Just make sure the name points to the correct file and folder path of your class in the current module and declare the namespace constant in the class.
Using a REST approach I want to be able to save more than one model in a single action.
class MyController extends ActiveController {
public $modelClass = 'models\MyModel';
}
class MyModel extends ActiveRecord {
...
}
That automagically creates actions for a REST api. The problem is that I want to save more than one model, using only that code in a POST will result in a new record just for MyModel. What if I need to save AnotherModel?
Thanks for any suggestion.
ActiveController implements a common set of basic actions for supporting RESTful access to ActiveRecord. For more advanced use you will need to override them or just merge to them your own custom actions where you will be implementing your own code & logic.
Check in your app the /vendor/yiisoft/yii2/rest/ folder to see how ActiveController is structured and what is doing each of its actions.
Now to start by overriding an ActiveController's action by a custom one, you can do it within your controller. Here is a first example where i'm overriding the createAction:
1-
class MyController extends ActiveController
{
public $modelClass = 'models\MyModel';
public function actions()
{
$actions = parent::actions();
unset($actions['create']);
return $actions;
}
public function actionCreate(){
// your code
}
}
2-
Or you can follow the ActiveController's structure which you can see in /vendor/yiisoft/yii2/rest/ActiveController.php by placing your custom actions in separate files. Here is an example where I'm overriding the updateAction by a custom one where i'm initializing its parameters from myController class :
class MyController extends ActiveController
{
public $modelClass = 'models\MyModel';
public function actions() {
$actions = parent::actions();
$custom_actions = [
'update' => [
'class' => 'app\controllers\actions\WhateverAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
'scenario' => $this->updateScenario,
'params' => \Yii::$app->request->bodyParams,
],
];
return array_merge($actions, $custom_actions);
}
}
Now let's say as example that in my new action file app\controllers\actions\WhateverAction.php I'm expecting the Post Request (which i'm storing in $params) to have a subModels attribute storing a list of child models to which I'm going to apply some extra code like relating them with their parent model if they already exists in first place :
namespace app\controllers\actions;
use Yii;
use yii\base\Model;
use yii\db\ActiveRecord;
use yii\web\ServerErrorHttpException;
use yii\rest\Action;
use app\models\YourSubModel;
class WhateverAction extends Action
{
public $scenario = Model::SCENARIO_DEFAULT;
public $params;
public function run($id)
{
$model = $this->findModel($id);
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $model);
}
$model->scenario = $this->scenario;
$model->load($this->params, '');
foreach ($this->params["subModels"] as $subModel) {
/**
* your code related to each of your model's posted child
* for example those lines will relate each child model
* to the parent model by saving that to database as their
* relationship has been defined in their respective models (many_to_many or one_to_many)
*
**/
$subModel = YourSubModel::findOne($subModel['id']);
if (!$subModel) throw new ServerErrorHttpException('Failed to update due to unknown related objects.');
$subModel->link('myParentModelName', $model);
//...
}
// ...
return $model;
}
}
So if I understand you wish to add a new database entry not only for the model you are querying, but for another model.
The best place to do this would be in the AfterSave() or BeforeSave() functions of the first model class. Which one would depend on the data you are saving.
Why do I get a
Class 'Search_Controller' not found
when doing this:
class Snippets_Controller extends Search_Controller {
public $restful = true;
public function get_index()
{
$snippets = Snippet::all();
$categories = Categorie::all();
return View::make('snippet.index')->with(array(
'snippets' => $snippets,
'categories' => $categories,
'active_categorie' => Session::get('active_categorie_id')
)
);
}
The Search Controller:
class Search_Controller extends Base_Controller {
protected static function build_html_for_search_results($search_results)
{
...
You should autoload this in you application start.php folder.
If you open that file, and you search for "Base_Controller", you will see something like this:
Autoloader::map(array(
'Base_Controller' => path('app').'controllers/base.php'
));
The only thing you have to do is add the search controller there:
Autoloader::map(array(
'Base_Controller' => path('app').'controllers/base.php',
'Search_Controller' => path('app').'controllers/search.php'
));
And that should do the trick.
Laravel loads controllers based on the name that's requested, and it doesn't autload any of the controllers, as it would be a waste of time for 90% of the controllers.