SonataAdminBundle show view with tabs - sonata-admin

I'm using SontaAdminBundle and I want to organise my show action on tabs.
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->tab('Infos personnelles')
->with('Beneficiary', array('class' => 'col-lg-6'))
->add('email')
->add('firstname')
->add('lastname')
->add('civility')
->add('dateOfBirth')
->add('enabled')
->add('address')
->end()
->end()
->tab('projects')
->with('projects')
->add('title')
->add('statusLabel')
->end()
->end();
}
But It doesn't work. Is there another config to do.
Thx

The config you used is good, you just need to update your version of sonata to master, check the changes in this commit:
https://github.com/sonata-project/SonataAdminBundle/commit/fd1a1596f86bfb4afdafe9767efaa4c787bba6a5
where the SonataAdminBundle/Resources/views/CRUD/base_show.html.twig was updated.
Hope this helps.

Related

How to use $this->autoRender = false in cakephp 3.6.10?

I am trying to display the test data on the screen by running function test() in the pagesController. Used $this->autoRender = false for it, but it is still giving me error:
Please help me out. I think some version problem is there, but I can't figure it out. Thankyou.
Cakephp by default takes Pages controller's display actions as a home page. display function manages pages and subpages itself that is why you are getting error. Either you can change your default home page in your /config/routes.php
$routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
OR
define your test action in some other controller.
OR
Remove code from display action
class PagesController {
function display()
{
// default controller code here
// your custom code here
}
}
Hope this will work.

CakePHP 3.5 redirect missing controller exception

I am struggeling with the missing controller exception thrown by CakePHP.
Once an unknown controller is called, it should redirect on my login page.
First I tried to route to my standart login page once there is an controller/action unknown.
//default routing
$routes->connect('/:controller', ['action' => 'index'], ['routeClass' => 'InflectedRoute']);
$routes->connect('/:controller/:action/*', [], ['routeClass' => 'InflectedRoute']);
$routes->connect('/', ['controller' => 'Users', 'action' => 'login']);
//redirect if controller is not known
$routes->connect('/*', ['controller' => 'Users', 'action' => 'login']);
However, this did not work at all, so I googled alot and it turned out that you should catch an the missing controller excpetion instead of rerouting. I can't find out where the error can be caught and it's very little written about it.
Did anyone already have something to do with it?
Short answer
As far as I know catching the MissinControllerException can only be done by customizing the Error Handling flow in Cakephp
Longer answer
To achieve the result you want to need to do the following.
If you are using Middleware in your Application class you need to disable the Error Handling middleware by commenting out this line:
->add(ErrorHandlerMiddleware::class)
Next you need to overwrite the default CakePHP Error handler with a custom one. So in src\Error create the file AppError.php with contents similar to this:
class AppError extends ErrorHandler
{
public function _displayException($exception)
{
if($exception instanceof MissingControllerException){
$response = new Response();
$response = $response->withLocation(Router::url(
['controller'=>'Users', 'action'=>'login'])
);
$emitter = new ResponseEmitter();
$emitter->emit($response);
}else{
parent::_displayException($exception);
}
}
}
Finally, in your bootstrap.php file you need to register your new Error handler. As per docs something like this needs to be added:
$errorHandler = new \App\Error\AppError();
$errorHandler->register();
Potential problems
Doing this redirect will hide away all of your missing controller exceptions. This may cause you trouble in case of typo's in the URL, since you will no longer get a clear error, but instead be redirected to the login page. The error.log file should still show you the original exception.
Good luck!
Potential Problems 2 - CakePHP >= 3.6.x
As pointed out by ndm in the comments disabling the Error Handling Middleware is not always a good idea, especially for CakePHP 3.6. In this case a better solution is to extend the ErrorHandling Middleware and register that.
You could try to handle this exception using custom Exception Renderer:
In src/Error create a new file, named eg MyExceptionRenderer.php, and handle missing controller exception there:
namespace App\Error;
use Cake\Error\ExceptionRenderer;
class MyExceptionRenderer extends ExceptionRenderer
{
public function missingController($error)
{
return $this->controller->redirect("/");
}
}
You will need also to enable this custom renderer in config/app.php:
'Error' => [
'errorLevel' => E_ALL,
'exceptionRenderer' => 'App\Error\MyExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
With this, when MissingControllerException will be raised, user will be redirected, in this case to main page.
More info can be found here:Error Handling

Add form option in sonata admin class

How can I add custom option to formmMapper in sonata admin class?
I have form related to entity in admin class. For some reason I want to add my own options to one of the field
$formMapper
->with('tab.dimension')
->add('dimension', 'collection', array(
'type' => 'dimension_product',
'allow_add' => true,
'allow_delete' => true,
'required' => false,
'my_custom_options' => false,
))
->end();
Unfortunatly it is not possible in this way,because this options isn't defined in resolver.
But I have no access to resolver in "normal way".
Sonata defined form builder in two methods:
public function getFormBuilder()
{
$this->formOptions['data_class'] = $this->getClass();
$formBuilder = $this->getFormContractor()->getFormBuilder(
$this->getUniqid(),
$this->formOptions
);
$this->defineFormBuilder($formBuilder);
return $formBuilder;
}
public function defineFormBuilder(FormBuilder $formBuilder)
{
$mapper = new FormMapper($this->getFormContractor(), $formBuilder, $this);
$this->configureFormFields($mapper);
foreach ($this->getExtensions() as $extension) {
$extension->configureFormFields($mapper);
}
$this->attachInlineValidator();
}
Allowed options are defined in this object:
new FormMapper($this->getFormContractor(), $formBuilder, $this);
Could somebody give me advice how can i add my own option?
Little bit late to the party, but it sort of depends on what you want to do with this option.
If you need to add a real custom form option, it is not very much different from working directly with Symfony forms. You can add extra options and functionality to a given form type using a form extension . You could even add functionality to the sonata form types this way.
If you simply need to pass an option from one Admin to a child Admin (which I think you might want to do), you can use the field description options rather than the actual form options:
$formMapper
->with('tab.dimension')
->add('dimension', 'collection', array(
'type' => 'dimension_product',
'allow_add' => true,
'allow_delete' => true,
'required' => false,
), array(
'my_custom_options' => false,
))
->end();
Now in your child Admin you can retrieve these options using
$this->getParentFieldDescription()->getOptions();
To be used to configure your child Admin.

Cakephp: Escape paginator prev link

I'm using the prev link for the Paginator component like so:
<?php echo $this->Paginator->prev('‹', array('escape'=> false), null, array('escape' => false)); ?>
This produces an escaped version of of ‹ when the link is active but does not escape the HTML when the link is disabled.
I'm using CakePHP 2.4
Additional details:
My model, controller and view is in the Plugin folder
My model is not using a database i.e. var $useTable = false;. I get my data
via a web service.
I've overridden the paginate function in my model so that I can call the paginated web service.
Are you using BoostCake?
I was having the exact same problem. Active links were being escaped, but disabled ones were not.
I disabled the "BoostCake.BoostCakePaginator" plugin, and all is working fine, so I would assume a bug in that plugin. (I have no time to investigate at the moment, but if/when I do, I will report back.)
like gaurav sharma said, there is a bug.
you should replace $this->link($title) in return-value of public function prev(...) and public function next(...) in BoostCakePaginatorHelper.php (ln94 & ln121) by $this->link($title, NULL, array('escape' => false))
like this:
return parent::prev($title, $options, $this->link($title, NULL, array('escape' => false)), array_merge($options, array(
'escape' => false,
'class' => $disabled,
)));

Using prefixes instead of extensions in CakePHP

I'm trying to implement REST and parseExtension like functionality in my app, running on CakePHP 2.
Instead of having URLs like http://myapp.dev/controller/action.json I would like to use http://myapp.dev/json/controller/action.
The reason for this is that sometimes extensions look a little stupid when put onto something like http://myapp.dev/controller/index/show:10/page:2.json.
While this could be implemented in a custom route, I already have lots of custom routes, and do not want to have to create duplicates of each with a :type field in there for maintenance reasons.
What would be ideal is setting it up such that any url with /json /xml /html etc. in first place would be treated as if json, xml, html etc. were the extension.
While Prefix Routing looks ideal for this, it requires new methods (e.g. json_index, html_index etc. and I would have to specify each format as a separate prefix).
Is there any good way of doing this? I just want parseExtensions to instead be like a parsePrefixes method instead.
You should try the following :
Router::connect('/:ext/', array(':ext'), array('pass' => 'ext'));
Router::connect('/:ext/:controller/*', array(':ext'), array('pass' => 'ext'));
Router::connect('/:ext/:controller/:action/*', array(':ext'), array('pass' => 'ext'));
Then, the router will pass the :ext argument, in the "ext" value of the route parameters. Add it for all your rules !
If you want to use traditionnel routes to work, you need to use a custom CakeRoute. Create a file "/libs/routes/RestRoute.php" in your app folder, add the following into it :
class RestRoutes extends CakeRoute {
function parse($url) {
$params = parent::parse($url);
if (empty($params)) {
return false;
}
if(!in_array($params['ext'], Router::extensions())) {
return false;
}
return $params;
}
}
And in your /core/routes.php :
App::import('Lib', 'routes/RestRoute');
Router::connect('/:ext/', array(':ext'), array('pass' => 'ext', 'routeClass' => 'RestRoute'));
Router::connect('/:ext/:controller/*', array(':ext'), array('pass' => 'ext', 'routeClass' => 'RestRoute'));
Router::connect('/:ext/:controller/:action/*', array(':ext'), array('pass' => 'ext', 'routeClass' => 'RestRoute'));
So, when your custom route won't be able to pass an url, it would try the default url, without the ext parameters. Otherwise, the order of the parameters are not quiet allright.
Maybe not the best or cleaner solution, but it's a good start.

Resources