Hello i am trying to implement a helper extends the Html helper.
I created based on the documentation the below empty custom helper
<?php
namespace App\View\Helper;
use Cake\View\Helper;
use Cake\View\Helper\HtmlHelper;
use Cake\View\View;
/**
* MyHtml helper
*/
class MyHtmlHelper extends HtmlHelper
{
public function __construct(View $view, $config = []) {
parent::__construct($view, $config);
}
/**
* Default configuration.
*
* #var array
*/
protected $_defaultConfig = [];
}
I load both of them on AppController but when i use them on the view I receive the expected result from Html helper but not from custom helper why ? (the second helper doesn't return an error but just an empty result)
<?php echo $this->Html->tag('div','oti na einai2'); ?>
<?php echo $this->MyHtml->tag('div','oti na einai'); ?>
You broke it by overriding the parents default settings.
protected $_defaultConfig = [];
See the API documentation.
Merge whatever you need in the constructor for example instead of overriding the whole property with an empty array.
Related
I have written a CakePHP plugin https://github.com/anuj9196/CakePHP-App-Installer
The plugin is using default.ctp layout from plugin_path/src/template/layout/default.ctp
When there is some other theme used in the host application. Like in my case I have setup one in AppController's beforeRender()
$this->viewBuilder()->setTheme('DashboardTemplate');
DashboardTemplate is in application's /plugin/ directory.
Now, when I access my plugin's URL using example.com/installer/install
The template loads on top of DashboardTemplate theme.
How can I disable them in plugin's AppController?
The AppController inside plugin directory contains
<?php
namespace Installer\Controller;
use App\Controller\AppController as BaseController;
class AppController extends BaseController
{
// nothing here
}
Remove the theme by using beforeRender() in your plugin's AppController.
<?php
namespace Installer\Controller;
use App\Controller\AppController as BaseController;
class AppController extends BaseController
{
/**
* #param \Cake\Event\Event $event The beforeRender event.
* #return \Cake\Http\Response|null|void
*/
public function beforeRender(Event $event)
{
try {
return parent::beforeRender($event);
} finally {
$this->viewBuilder()->setTheme(null);
}
}
}
You can switch between layouts in your view and controllers fairly easily.. using plugin syntax
// inside controller
$this ->layout = 'Plugin.layout';
//inside view template
$this ->layout = 'Plugin.layout';
If you just want to disable the theme, use Mathew's method above. But be careful that will disable the theme for the whole application not just this plugin in case some of your app code is ran after your plugin
I need to render an XML+XSL template in my application, and it used to work with cakePHP 3.0. I have made the switch to 3.1 recently and it has stopped working. The problem is that I was having a formatted view of my XML, while now I just get a plain string.
The migration guide says something about some changes in the RequestHandlerComponent, but nothing helpful (or maybe it's just me and I don't get the point :)).
This is my controller (it is exactly as it was with Cake3.0):
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Utility\Xml;
use Cake\Event\Event;
use Cake\Routing\Router;
use Cake\ORM\TableRegistry;
use Cake\Filesystem\Folder;
use Cake\Filesystem\File;
use Cake\Network\Email\Email;
use Cake\Core\Configure;
use Cake\I18n\Time;
/**
* Invoices Controller
*
* #property App\Model\Table\InvoicesTable $Invoices
*/
class InvoicesController extends AppController
{
public $components = [
'Browser',
'Reorder11'
];
public $helpers = [
'Multiple'
];
public $paginate = [];
public function initialize()
{
parent::initialize();
$this->loadComponent('Paginator');
$this->loadComponent('RequestHandler');
}
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow(['demo']);
}
/*
* ... several other functions ...
*/
public function viewxml($id = null)
{
$this->viewBuilder()->layout('xml');
$invoice = $this->Invoices->myInvoice($id, $this->Auth->user('id'));
$this->RequestHandler->respondAs('xml');
$this->set('invoice', $invoice);
}
}
The xml.ctp layout, which is really simple
echo $this->fetch('content');
and the viewxml.ctp template just echoes the xml as a string.
How can I obtain the formatted XML+XSL again?
Try add: $this->response->header(['Content-type' => 'application/xml']);
I had the same error but my output was pdf
working 3.0.14 using this code:
$this->RequestHandler->respondAs("pdf");
$this->layout = 'pdf/default';
$this->view = 'pdf/report1_pdf';
for 3.1.x (this works if u save the file and open later, if you try to open it directly on browser its print the plain file content as a txt/html):
$this->viewBuilder()->layout('pdf/default');
$this->viewBuilder()->template('pdf/report1_pdf');
$this->RequestHandler->respondAs('pdf');
$this->response->header(['Content-type' => 'application/pdf']);
i have a Fonctionnaire entity class that contains ManyToOne property to Grade entity class. when i want to add the idGrade field to ConfigureListField of FonctionnaireAdmin (using SonataAdmin) i got this error:
An exception has been thrown during the rendering of a template ("You must define an associated_property option or create a Proxies\__CG__\Examens\ExamensBundle\Entity\Grade::__toString method to the field option idGrade from service examens.examens.admin.fonctionnaire is ") in SonataDoctrineORMAdminBundle:CRUD:list_orm_many_to_one.html.twig at line 19.
Fontionnaire.php class:
<?php
namespace Examens\ExamensBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Fonctionnaire
*/
class Fonctionnaire
{
//...//
/**
* #var \Examens\ExamensBundle\Entity\Grade
*/
private $idGrade;
//...//
}
FonctionnaireAdmin.php:
<?php
namespace Examens\ExamensBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Examens\ExamensBundle\Entity\Fonctionnaire;
class FonctionnaireAdmin extends Admin
{
protected $datagridValues = array(
'_sort_order' => 'ASC',
'_sort_by' => 'codeFonctionnaire'
);
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('nomAr','text',array('label'=>'Nom arabe'))
->add('prenomAr','text',array('label'=>'Prénom arabe'))
->add('nomFr','text',array('label'=>'Nom français '))
->add('prenomFr','text',array('label'=>'Prénom français'))
->add('nomUtilisateur','text',array('label'=>'nom Utilisateur'))
->add('motDePasse','text',array('label'=>'motDePasse'))
->add('idGrade','entity',
array('class' => 'Examens\ExamensBundle\Entity\Grade',
'property' => 'libGradeAr'))
->add('dateNominationGrade','date',
array('years' => range(1980, date('Y'))))
;
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('nomAr')
->add('prenomAr')
->add('nomFr')
->add('prenomFr')
->add('nomUtilisateur')
->add('motDePasse')
->add('idGrade')
->add('dateNominationGrade')
;
}
}
You can just add:
->add('idGrade', null, array('associated_property' => 'libGradeAr'))
You just need to add a __toString() method to your Grade class. Something like :
public function __toString() {
return $this->nomAr;
}
It will be used by SonataAdminBundle to display the name of your current object.
Don't forget you also can use it as follow to prevent Sonata from generating a name for you when creating a new object:
public function __toString {
// Show name if it exist otherwise just show a custom label
return $this->nomAr ? $this->nomAr : 'Custom new label name';
}
I have created helper name TicketHelper (has TicketsController), CommonHelper (no controller) and ExcelHelper (no controller). Inside TicketHelper it work fine when called any function of CommonHelper. Here example TicketHelper:
<?php
class TicketHelper extends AppHelper {
public $helpers = array('Session','Common');
public function myFunction(){
echo $this->Common->workfine();
}
?>
By the same action i called CommonHelper to ExcelHelper it produces error: Fatal error: Call to a member function workfine() on a non-object in
After many hours check, i found mistake problem with constructor
<?php
class TicketHelper extends AppHelper {
public $helpers = array('Session','Common');
public function myFunction(){
echo $this->Common->workfine();
}
//Here my problem constructor Note: function name and class name are the same
function TicketHelper (){
//My code here
}
/**
* It should be follow cakephp doc
* function __construct($id = false, $table = null, $ds = null) {
* parent::__construct($id, $table, $ds);
*
* }
*
*/
?>
You should not use a helper inside a controller. A helper is used for logic in the view. It is included in the controller but accessible in the view. For logic shared between controllers, use a component instead http://book.cakephp.org/2.0/en/controllers/components.html#creating-a-component.
If you still want to use a helper in the controller (not recommended):
$view = new View($this);
$myHelper = $view->loadHelper('MyHelper');
Currently i am using something like this:
//at bootstrap.php file
Configure::write('from', 'mymail#mydomain.com')
//at controllers or models files
$var = Configure::read('from')
The thing is, i would like to manage that variable through the database to be able to modify it in a simpler way.
I was thinking about doing it with AppModel but then it would only be accessible for Models and not controllers.
What should I do in this case?
Thanks.
You can create a separate model / plugin which will be mapped to a configuration table in your database. Then load it through $uses statement for controllers and App::import() for models.
class SystemSetting extends AppModel {
/**
* Return a list of all settings
*
* #access public
* #return array
*/
public function getSettings() {
return $this->find('all');
}
}
Then, in your controller:
class SomeController extends AppController {
var $uses = array('SystemSetting');
public function displaySettings() {
$settings = $this->SystemSetting->getSettings();
// .. your code
}
}
In model:
App::import('Model', 'SystemSettings.SystemSetting');
$settings = new SystemSetting();
$mySettings = $settings->getSettings();
This works just fine. Of course, you might also load settings in both AppController and AppModel to follow the DRY rule.
create the getSettings in your AppModel
in AppController you can write this method:
public function getSettings() {
return $this->{$this->modelClass}->getSettings();
}
this way the getSettings() method is available in any model and any controller
any model call:
$mysettings = $this->getSettings();
any controller call:
$mysettings = $this->MODELNAME->getSettings();