Symfony2 - ChoiceType - get choice list from JSON without JS - json

I have a JSON file with all world languages and would like to put them into choices array inside ChoiceType form field.
$builder->add('languages', ChoiceType::class, array(
'choices' => array()
))
My JSON file is stored: projectname/web/bundles/index/json/languages.json
Is it possible to achieve it without writing JS / AJAX?
P.S. EventListeners or other alternatives that Symfony2 provides suits me well.

You could reach the file with DIR, since I dont' know where the php file with builder is located, it could looks like:
$builder->add('languages', ChoiceType::class, array(
'choices' => json_decode(
//if builder is in controller, this should work
file_get_contents(__DIR__.'/../../../web/bundles/index/json/languages.json'),
true)
));

Related

Yii2 load all models automatically

I don't like to declare every model as
use app\models\Country;
Really it bothers me a lot. I like the approach used in Yii 1.15 when you could load all models using import instruction in config like:
'import' => array(
'application.models.*',
)
Yes, I know it's not good for performance. But I have not more than 50 models and I care much more about my own performance rather than of performance of machine.
I had no luck in figuring out how to do it Yii2.
All I found out is that it should be done via bootstrap option in main config file.
I tried the following:
$config = [
'language' => 'en',
'id' => 'basicUniqueApp',
'basePath' => dirname(__DIR__),
'bootstrap' => [
'log',
'app\models\*'
],
But it's not proper syntax.
Any ideas?
You're trying to break down PHP namespace. That's not a good idea.
If you don't want declare on top model, You can call directly without declare like this:
$country = new \app\models\Country();

CakePHP jSon format change

I'm finding list of Areas for my CakePHP 2.x website and it supports, JSON output as below with find all method:
$this->Area->find('all', array('fields' => array('id', 'name', 'order'), 'conditions' => array('Area.status' => 1)));
Below is my JSON output:
[{"Area":{"id":"2","name":"Area 1","order":"1"}},{"Area":{"id":"3","name":"Area 2","order":"1"}}]
Now Is that possible for me to remove Area tag which is repeating everytime?
Any patch for same? Do let me know if any suggestions / ideas.
on your view for output json write this:
echo json_encode(Set::extract('/Area/.', $area));
For me works fine.
CakePHP Provides some in-built library functions for data extraction from result set and output same as JSON format.
// initialize your function to render false and response type json
$this->autoRender = false; // no view to render
$this->response->type('json');
// Remove Area from array and encode
$area = Set::extract('/Area/.', $area);
$json = json_encode( $area);
$this->response->body($json);
Hope it helps !

An easy way to load ACL in Zend Framework 2?

I have been following this guide to load my menu configuration and i think it is very nice and clean way to load the menu.
My question is simple, is there a way to load your ACL configuration on the same way with a config array and some kinda of factory?
If there isn't, how do i load a ACL configuration and use with that menu in a easy way?
Thanks!
Edit:
This is a very good blog post on why use modules that is already done and not make your own, http://hounddog.github.com/blog/there-is-a-module-for-that/
ZF2 contains ACL and also RBAC (role based ACL - might be in ZF2.1), but to put it in place, easier is to use module which you can plug into your application. BjyAuthorize seems to me a bit bloated, you have to use ZfcUser module. I prefer ZfcRbac, the ACL rules are based on user roles (group) and their access to controller, action or route. Configuration stored in one config file, really easy to implement.
Most likely there are several ways to do it, but I prefer to do it in getViewHelperConfig() of application's Module.php (here I use BjyAuthorize module to simplify work with ACL, and in particular it allows to set ACL rules in configuration file module.bjyauthorize.global.php)
public function getViewHelperConfig()
{
return array(
'factories' => array(
'navigation' => function($sm) {
$auth = $sm->getServiceLocator()->get('BjyAuthorize\Service\Authorize');
$role = $auth->getIdentityProvider()->getIdentityRoles();
if (is_array($role))
$role = $role[0];
$navigation = $sm->get('Zend\View\Helper\Navigation');
$navigation->setAcl($auth->getAcl())->setRole($role);
return $navigation;
}
)
);
}
Play with This structure . get role and resource from database and save this in session for or any caching .
You are right, there is no out-of-the-box-all-in-one solution. You have to build some bridges between the modules.
Another easy way to integrate BjyAuthorize is using **Zend Navigation**s default methods as described by Rob Allen:
Integrating BjyAuthorize with ZendNavigation
$sm = $e->getApplication()->getServiceManager();
// Add ACL information to the Navigation view helper
$authorize = $sm->get('BjyAuthorizeServiceAuthorize');
$acl = $authorize->getAcl();
$role = $authorize->getIdentity();
ZendViewHelperNavigation::setDefaultAcl($acl);
ZendViewHelperNavigation::setDefaultRole($role);
You can also use ZfcRbac and use a listener to make it work with Zend Navigation.
Since this is a lot of code I simply post the link here:
Check Zend Navigation page permissions with ZfcRbac – Webdevilopers Blog
I've just created an ACL module that creates an ACL Service parsing the routes.
To manage your access control to your application you only need to define roles and add a new key 'roles' in every route. If you do not define that key or its array is empty, then the route becomes public. It also works with child routes.
As an example:
array(
'router' => array(
'routes' => array(
'user\users\view' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin/users/view/id/:id/',
'constraints' => array(
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'User\Controller\Users',
'action' => 'view',
'roles' => ['admin', 'user'],
),
),
),
),
),
);
The module can be installed via composer and it is now listed in the zend modules repository: http://zfmodules.com/itrascastro/TrascastroACL
You can get more detailed info about use and installation from my blog: http://www.ismaeltrascastro.com/acl-module-zend-framework/

Use a widget in a statically-called method

Normally a widget is used by calling CController::widget() on an instance of CController, typically $this in a view.
But if I'm writing a static method, a helper, say, then I don't have access to an instance of CController. So how do I use a widget?
Let's say further that this helper method is invoked in the eval()’ed expression in a CDataColumn's value property. That poor expression has almost no context at all. How should the helper use a widget?
EDIT: Code example
As requested, a view example:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'columns' => array(
array(
'name' => 'attrName',
'value' => '--USE WIDGET HERE--',
),
)
));
This answer doesn't answer the question in general but in the specific case—how to access the controller and use a widget in the context of the evaluated expression of CDataColumn::$value—you can use this:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'columns' => array(
array(
'name' => 'attrName',
'value' => function ($data, $row, $column) {
$controller = $column->grid->owner;
$controller->widget(/* ... etc ... */);
},
),
)
));
The trick was discovering that CDataColumn::renderDataCellContent() uses CComponent::evaluateExpression(), which injects the component instance into the callback as the last parameter. In this case that omponent is the CDataColumn, which references the controller as shown.
I don't like writing PHP expressions as string literals so I'm pleased to find this option.
A comment on http://www.yiiframework.com/doc/api/1.1/CDataColumn#value-detail shows another way to us a widget in a column value that I haven't tried.
This one is working solution for calling widgets in static methods in Yii
Yii::app()->controller->widget('widget');
There's no direct way to call a widget out of controller because you shouldn't do so. It's all about MVC. Widgets are only needed and/or useful in views, and views are only accessed via controllers. That's the theory.
I guess you're approaching the problem mistakenly. A proper, MVC-friendly way to do what your're trying to do involves using renderPartial(). You know: you a have certain content and you want to decorate it (in your case you want to imbibe it inside a widget, right?) before displaying it to final user; so, from the view, you call renderPartial(). It will send your data to a file where it will properly decorated. renderPartial() returns the content properly formatted and now you can display it in the view.
Unfortunately, in your particular case, you're working with grid view (right?) and, at least from my point of view, it makes the things a bit harder. In order to decorate content for a CGridColumn-subclass element (like CDataColumn), you need to override the renderDataCellContent() method. Check it out here: http://www.yiiframework.com/doc/api/1.1/CDataColumn#renderDataCellContent-detail

Zend Forms and Ext.grid.Panel

I am working for a company who use tabulated html/JS interfaces. These are home grown (real honest to god s) with query events attached to each cell. For the old usage they were suitable, but the interactions required between rows and cells are becoming much more complex on the client side. Specifically they want both server and client side validation.
To facilitate this, the devs I report to are super keen on Zend_Forms, and insist that to use a framework like ExtJS, they don't want to have to write back end and front end code twice (please ignore that if it's all home grown they'll have to do this anyway).
So with that in mind, I'm trying to leverage Zend_Form decorators to create Ext.grid.Panel column defintions. For this, I would need to use decorators to export an array (and then json it using the ViewHelper), or render a JSON string directly.
So this would be something like:
$dateElement = new Zend_Form_Element_Text('startDate', array(
'label' => 'Start Date',
'validators' => array(
new Zend_Validate_Date()
)
));
echo (string)$dateElement;
would output:
{ text: 'Start Date', dataIndex:'startDate', xtype:'datecolumn'}
or (obviously not with string cast, but maybe with ->toArray() or something):
array( 'text' => 'Start Date', 'dataIndex' => 'startDate', 'xtype' => 'datecolumn')
I think if I could get it to this stage, I could get what I need out of it.
Has anyone here tried to do anything similiar to this (getting a JSON/XML/other markups output, rather than HTML from Zend_Forms using Decorators) or if they could point me to any resources?
I think I have a solution...
Make a decorator similar to this:
class My_Form_JSON_Decorator extends Zend_Form_Decorator_Abstract{
protected $xtype;
protected $dataIndex;
public function __construct($dataIndex,$xtype){
$this->xtype=$xtype;
$this->dataIndex=$dataIndex;
}
public function render($content){
$element=$this->getElement();
$label=$element->getLabel
//if you need errors here too do the same with $element->getMessages();
return 'array ("text"=>"'.$label.'","dataIndex"=>"'.$this->dataIndex.'","datecolumn"=>"'.$this->xtype.'")';
}
}
Then, on the form, use something similar to this:
$dateElement = new Zend_Form_Element_Text('startDate', array(
'label' => 'Start Date',
'validators' => array(
new Zend_Validate_Date()
)
$dateElement->setDecorators(array(
new My_Form_JSON_Decorator("startDate","datecolumn");
));
And finally, on the View, you should have this:
{
Date: <?php echo $this->form->startDate; ?>,
}
I didn't tried the code above but, I did it with a similar code I used once when I needed to change Decorators of a Form.
It could not be all correct but, I think that it shows you a way of doing that.
Good work =)