Yii2 override common extension/widget view - php

I have a widget class inside "~/common/extensions/my_widget"
It renders: "~/common/extensions/my_widget/views/index"
public function run()
{
echo $this->render( '#common/extensions/my_widget/views/index');
}
When i make a new application in "~/myapplication/"
how is it possible to override the widget view for only "myapplication" and if there is no view found, use the default view.
~ is my basefolder

Inside config, add your view:
'components' => [
...
'view'=> [
'theme' => [
'pathMap' => [
'#common/extensions/my_widget/views' => [
'#myapplication/views/widgets/my_widget/views', // Override
'#common/extensions/my_widget/views', // Default
],
],
],
]
],

Related

Registering custom Form View Helper

With ZF2, it was very simple to register custom view helpers for custom form elements.
You could simply create an element like such:
use Zend\Form\Element;
class Recaptcha extends Element
{
protected $attributes = [
'type' => 'recaptcha',
];
protected $secret;
public function getSecret()
{
return $this->secret;
}
public function __construct($secret)
{
parent::__construct();
$this->secret = $secret;
}
}
Create a matching helper:
use Zend\Form\ElementInterface;
use Zend\Form\View\Helper\FormElement;
class Recaptcha extends FormElement
{
public function render(ElementInterface $element)
{
return '<div class="form-group">
<div id="register_recaptcha">
<div class="g-recaptcha" data-sitekey="' . $element->getSecret() . '"></div>
</div>
</div>
<script src="//www.google.com/recaptcha/api.js"></script>';
}
}
And then wire it up at config:
return [
'form_elements' => [
'factories' => [
Recaptcha::class => RecaptchaFactory::class,
],
],
'view_helpers' => [
'invokables' => [
'recaptcha' => RecaptchaHelper::class,
],
],
];
IIRC, you would have to wire it up in the Bootstrap too
public function onBootstrap($e)
{
$application = $e->getApplication();
$services = $application->getServiceManager();
$services->get('ViewHelperManager')->get('FormElement')->addType('recaptcha', 'recaptcha');
}
Upgrading a project from ZF2 to ZF3, the custom element now appears as a textfield.
If I call the helper directly on the field, it renders properly:
{{ recaptcha( user_form.get('recaptchafield') ) | raw }}
It's the automatic association that's seemingly vanished. Such that calling formRow on each doesn't invoke the helper.
Anyone have the quick fix? Hopeful to save myself from reviewing the actual zend-form and zend-view code.
Thank you!
I had the same issue and I resolved it by replacing
$services->get('ViewHelperManager')->get('FormElement')->addType('recaptcha', 'recaptcha');
with
$services->get('ViewHelperManager')->get('FormElement')->addClass(Recaptcha::class, RecaptchaHelper::class);
The config also needed some adaption. It now reads like this:
return [
'form_elements' => [
'factories' => [
Recaptcha::class => RecaptchaFactory::class,
],
],
'view_helpers' => [
'invokables' => [
RecaptchaHelper::class => RecaptchaHelper::class,
],
],
];
Hope that helps someone else find the issue faster ;)
Invokables no longer exist in ZF3. You need to move your recatpcha view helper to the factories key instead and wire it up to Zend\ServiceManager\Factory\InvokableFactory::class

Yii 2 and jQuery

Due project requirements I have to use a different version of jQuery than the one which comes with Yii2. I know I can disable it by using:
'assetManager' => [
'bundles' => [
// you can override AssetBundle configs here
'yii\web\JqueryAsset' => [
'sourcePath' => null,
'js' => []
],
],
],
Then I go to AppAsset:
class AppAsset extends AssetBundle
{
public $sourcePath = "#app/themes/v1/assets";
public $jsOptions = [ 'position' => \yii\web\View::POS_END ];
public $js = [
"js/lib/jquery/jquery-1.9.1.js",
];
}
But this brings one big issue, jquery loads after yii.validation, etc:
</script><script src="/assets/5b466ff1/yii.js?v=1465857632"></script>
<script src="/assets/5b466ff1/yii.validation.js?v=1465857632"></script>
<script src="/assets/5b466ff1/yii.activeForm.js?v=1465857632"></script>
<script src="/assets/98d185b3/js/lib/jquery/jquery-1.9.1.js?v=1466702133"></script>
My temporal solution is changing POS_END to POS_HEAD, but that affects page SEO right?, as far as I know is considered bad practice to load js on head.
So my question is:
How can I load jQuery from my theme assets, using POS_END and loading before yii.validation etc?
A possibility is to add it on web/js/jquery.js but I would prefer to keep it on the assets bundle.
Any ideas?
Update:
Adding this to AppAsset allows me to have control on the theme itself. It is cleaner than modifying the global config.
public function init()
{
parent::init();
Yii::$app->assetManager->bundles['yii\\web\\JqueryAsset'] = [
'js' => ['lib/jquery/jquery-1.9.1.js'],
'sourcePath' => '#app/themes/v1/assets/js'
];
}
Just Change Your Config Code as :
'assetManager' => [
'bundles' => [
'yii\web\JqueryAsset' => [
'js' => ['lib/jquery/jquery-1.9.1.js'],
'sourcePath' => '#app/themes/v1/assets/js'
]
]
]
No Need to Define jquery in AppAsset
class AppAsset extends AssetBundle
{
public $sourcePath = "#app/themes/v1/assets";
public $jsOptions = [ 'position' => \yii\web\View::POS_END ];
public $js = [
//"js/lib/jquery/jquery-1.9.1.js" Not Required
];
}

Yii2: configure yii\web\ViewAction::$viewPrefix

I want to change default directory ("pages") of static pages views, using yii\web\ViewAction. Documentation says:
You may configure yii\web\ViewAction::$viewPrefix to change the
directory for searching these views.
Question: where and how need I to change this property? I tried to do it in controller:
use yii\web\ViewAction;
...
public function actions()
{
(new ViewAction)->viewPrefix = ''; //wanted to do it just as '#app/views/site/', without any subdirectory ('pages' or others)
return [
'stat' => [
'class' => 'yii\web\ViewAction',
],
];
}
But no success.
Try to set viewPrefix to null
public function actions()
{
return [
'stat' => [
'class' => 'yii\web\ViewAction',
'viewPrefix' => null,
],
];
}

Yii::configure does not work in module init()

I have a module calls API, and i want to load config file for it. The guide says that i have to use function \Yii::configure. I use it, but it doesn't apply any new configs. And i tried to use array instead config file, the result is same
class API extends \yii\base\Module
{
public $controllerNamespace = 'api\client\controllers';
public function init()
{
parent::init();
// \Yii::configure($this, require(__DIR__ . '/config/main.php'));
\yii::configure($this, [
'components' => [
'user' => [
'class' => 'yii\web\UserTest',
'identityClass' => 'api\client\models\User',
],
]
]);
echo \yii::$app->user->className();
die();
}
}
How I can override config in my module ?
UPDATE
You have to use setComponents method of Yii::$app
Yii::$app->setComponents(
[
'errorHandler'=>[
'errorAction'=>'forum/forum/error',
'class'=>'yii\web\ErrorHandler',
],
'user' => [
'class' => 'yii\web\User',
'identityClass' => 'app\modules\profile\models\User',
],
]
);
OLD ANSWER
Didn't it give you errors? Your casing are wrong and so instead of "yii" in small letters use "Yii" capitalized
class API extends \yii\base\Module
{
public $controllerNamespace = 'api\client\controllers';
public function init()
{
parent::init();
\Yii::configure($this, [
'components' => [
'user' => [
'class' => 'yii\web\UserTest',
'identityClass' => 'api\client\models\User',
],
]
]);
echo \Yii::$app->user->className();
die();
}
}
I see no reason to override the application components here. I'd use #StefanoMtangoo trick but to set the component to the Module itself instead of Yii::$app:
public function init()
{
parent::init();
$this->setComponents([
'db' => [
'class' => 'yii2tech\filedb\Connection',
'path' => '#app/builder/data',
]
]);
}
Then the tricky part is to differentiate between any app's components and your module's own components. For example if my Module had a model extending yii\db\ActiveRecord I'd override its getDB() as follow (original code here):
public static function getDb()
{
return Yii::$app->getModule('api')->get('db');
// instead of: return Yii::$app->getDb();
}
So whatever the app that is using my module has or hasn't a db component it won't matter.

How to use Twig template engine with Yii2 framework?

I followed the instructions on yii2 documentation about using twig template engine
in config/web.php (which is included from index.php) I have:
'view' => [
'class' => 'yii\web\View',
'renderers' => [
'twig' => [
'class' => 'yii\twig\ViewRenderer',
'cachePath' => '#runtime/Twig/cache',
'options' => ['auto_reload' => true], /* Array of twig options */
'globals' => ['html' => '\yii\helpers\Html'],
],
],
],
in SiteController.php:
public function actionIndex()
{
echo $this->render('index.twig');
}
in views/site/index.twig I have some text:
But instead of seeing raw html I see template based on views/layouts/main.php with index.twig content used as variable in main layout.
It was required to set layout to false in order to skip layout processing during redner
class BaseController extends Controller
{
public $layout = false;
}

Categories