How should I use Component in Helper? - cakephp

I used AkismetComponent in AkisHelper and my AkisHelper code is:
<?php
App::uses('AppHelper', 'View/Helper');
class AkisHelper extends AppHelper {
public $helpers = array('Html');
public $components = array('Akismet');
function isValid() {
if ($this->Akismet->isKeyValid()) {
echo 'OK';
} else {
echo 'Error';
}
}
}
But this error occured:
Error: Call to a member function isKeyValid() on a non-object
File: /var/www/cakeblog/app/View/Helper/AkisHelper.php
Line: 10
Please help me to solve my problem.
Thanks

Your not supposed to be able to n_n.. It's not MVC, it's like trying to call a controller method inside the view.
However you could always pass a variable to the view in your Akismet component, something like:
class AkismetComponent extends Component {
private $controller;
public function initialize($controller) {
$this->controller = $controller;
//here I pass a variable to the view
$this->controller->set('isKeyValid',$this->isKeyValid());
}
and in your view use it like any other variable:
if(isset($isKeyValid) && $isKeyValid){
}
Anyway, if you don't want to change the component, you could still pass the variable from the controller.
The view should be used only to display the information. Helpers should be only functions to help you with that, but they are not supposed to do business logic.
Hope this helps

Related

in cakephp4 how to access a model within a model

How do i access another model within a model in cakephp4.2? The docs on this issue isnt clear to me and i can then run a query on this ? TableRegistry is deprecated now.
error Unknown method "getTableLocator" called on App\Model\Table\LessonsTable
//none of these no longer work
in model {
use Cake\ORM\Locator\LocatorAwareTrait;
class LessonsTable extends Table
{
..
private function getlessonRevenue(){
//$clients = $this->getTableLocator()->get('Clients');
// $cleints = TableRegistry::get('Clients');
// $this->Table = TableRegistry::get('Clients');
$clients = $this->getTableLocator()->get('Clients');
https://api.cakephp.org/4.0/class-Cake.ORM.TableRegistry.html
Try:
<?php
use Cake\ORM\Locator\LocatorAwareTrait; //<------------ add here
class ArchivesTable extends Table
{
use LocatorAwareTrait; // <--------------------------- and add here
public function myMethod()
{
$clients = $this->getTableLocator()->get('Clients');
}
and read https://book.cakephp.org/4/en/orm/table-objects.html#using-the-tablelocator
and learn how to use php trait https://www.phptutorial.net/php-tutorial/php-traits/

How to implement a default view in CakePHP?

In CakePHP each method of a Controller has its own View and the view template file is the name of the method.
class DataController extends AppController
{
public function one()
{
// will render one.ctp
}
public function two()
{
// will render two.ctp
}
}
Accourding to the API documentation there is a $view property of the Controller that specifies the view to render. So I should have the ability to specify a default view file, say all.ctp, for all methods of a controller
class DataController extends AppController
{
public $view = 'all';
public function one()
{
// should render all.ctp
}
public function two()
{
// should render all.ctp
}
}
However this does not work and CakePHP ignores the $view property and continues to look for the template file of the same name as the method.
Is there a way to have a default view without having to insert $this->render('all'); in each of the Controller's methods?
The value is going to be overridden in Controller::setRequest() which is being called in the controllers class constructor.
You could use your controllers beforeFilter() callback instead to set the value:
public function beforeFilter()
{
parent::beforeFilter();
$this->view = 'all';
}

cakephp call a function of another model error

I have a site develop in cakephp 2.x
I want into my controller call a function of another controller like this:
class ProductsController extends AppController {
public $name = 'Products';
public $scaffold;
public $uses = array('Product','Unit');
public function testFunction(){
$this->loadModel('Unit');
$this->Unit->test();
}
}
The function test into UintController.php is this:
public function test(){
echo("test");
}
My model name are Product and Unit.
When I call the function test give me this error:
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'prova' at line 1
In the function now is empty but give me this error.
I have tried with:
public $uses = array('Unit');
and to cancel the line with $uses.
How can I solve it?
To call a function from another controller you can use the requestAction:
Definition
"This function calls a controller’s action from any location and returns data from the action. The $url passed is a CakePHP-relative URL (/controllername/actionname/params). To pass extra data to the receiving controller action add to the $options array".
Usage
This is what your code would looks like:
class ProductsController extends AppController
{
public $name = 'Products';
public $scaffold;
public $uses = array('Product','Unit');
public function testFunction() {
// Calls the action from another controller
echo $this->requestAction('/unit/test');
}
}
And then in the UnitController:
class UnitController extends AppController
{
public function test()
{
return 'Hello, I came from another controller.';
}
}
Warning
As said in the CakePHP Cookbook:
"If used without caching requestAction can lead to poor performance. It is rarely appropriate to use in a controller or model".
Best solution for you
But, the best solution for you, would be to create a function inside a model and then call from your controller, like this:
class ProductsController extends AppController {
public $name = 'Products';
public $scaffold;
public $uses = array('Product','Unit');
public function testFunction() {
echo $this->Unit->test();
}
}
And in the Unit model:
class Unit extends AppModel
{
public function test(){
return 'Hello, I came from a model!';
}
}

CakePHP: Find if is mobile browser in a helper (no access to request handler)

I need to know in a helper in a CakePHP application if the device is mobile, I would love to use $this->RequestHandler->isMobile(), but the request handler component is not available in helpers. Any ideas?
Thanks!
You can import the class and use it anywhere in the framework like so:
App::import('Component', 'RequestHandler'); // import class
$requestHandler = new RequestHandlerComponent(); // instantiate class
$isMobile = $requestHandler->isMobile(); // call method
var_dump($isMobile); // output: bool(true) or bool(false)
(Tested from helper and gives correct results for Firefox and iPhone)
Also, any options you set in the Controller::helpers property will be passed to the helper:
class AppController extends Controller {
public $components = array(/*...*/, 'RequestHandler');
public $helpers = array(/*...*/, 'MyHelper');
public function beforeFilter() {
$this->helpers['MyHelper']['mobile'] = $this->RequestHandler->isMobile();
}
}
You can catch the options array in your helper's constructor:
class MyHelper extends AppHelper {
protected $_defaultOptions = array('mobile' => false);
public function __construct($options) {
$this->options = array_merge($this->_defaultOptions, $options);
}
}
The accepted answer suggests using a component inside a helper which should be avoided as components are for use solely in controllers and will result in errors as mentioned by Anupal.
The simple solution is to use the CakeRequest class that RequestHandlerComponent uses. So in your helper you can do:-
App::uses('CakeRequest', 'Utility');
$isMobile = (new CakeRequest())->is('mobile');

Override model validate errors

I am new to CakePHP.
I would like to use the model validate mechanism, but I'm having trouble overriding the errors that are displayed. I am building an API where all the views need to be rendered in JSON and I have a JSON format that all errors need to output as. I've defined a custom AppError class and I have successfully be able to define custom errors in this format there.
Is there a way to use the AppError class to override the output of the error messages coming from validation?
Thanks.
I came up with a solution by adding these methods to my AppModel class:
function validates($options = array()) {
$result = parent::validates($options);
if (!$result) {
$this->_validateErrors();
}
return $result;
}
function _validateErrors() {
foreach ($this->validationErrors as $code) {
$this->cakeError('apiError', array('code' => $code)); // Custom JSON error.
return;
}
}
I then manually call $this->Model->validates() before a Model::save() call in my controller. This seems to be working well.
As far as I know, there's no direct way to get validation errors from within your AppError class. The way around it would be to create an AppModel class in app/app_model.php and use the onError() callback method to pass the error to your AppError class.
// app/app_model.php
class AppModel extends Model {
public function onError() {
// Pass the errors to your AppError class
AppError::someErrorMethod($this->getErrors());
}
}

Resources