Trying to get property on a non object Yii 1.1.15 - php

I try to change Css file for CGridView widget, in my config/main.php:
'components' => array(
'widgetFactory' => array(
'widgets' => array(
'CGridView' => array(
'cssFile' => Yii::app()->request->baseUrl . '/css/gridview.css',
),
),
),
...
And I get warning:
Trying to get property on a non object /path_to_project/protected/config/main.php on line 79
How I can suppress this warning, and why I getting it, in when I using it in view files it all works.
P.S. Yes I can set display_errors ini set to false and message will dissapearm but I want get clearly with it. Thanks!

The reason for the warning is that the CHttpRequest object Yii::app()->request has not been instantiated yet.
From the API page for CApplication:
CApplication will undergo the following lifecycles when processing a
user request:
load application configuration;
set up error handling;
load static application components;
onBeginRequest: preprocess the user request;
processRequest: process the user request;
onEndRequest: postprocess the user request;
Starting from lifecycle 3, if a PHP error or an uncaught exception occurs, the application will switch to its error handling logic and jump to step 6 afterwards.
Your error is happening at the first step. As such, Yii's error handling has not been setup yet. The only option is to suppress this warning using the # operator:
'cssFile' => #Yii::app()->request->baseUrl . '/css/gridview.css',
HOWEVER
This is a terrible idea, since you are essentially hiding the error instead of fixing it.
If your views are being displayed correctly (no css errors), you can omit the Yii::app()->request->baseUrl and just use:
'cssFile' => '/css/gridview.css'
If you are experiencing errors, you can create a class in your components folder that extends CWidgetFactory and set any variables that depend on other components here e.g
class MyWidgetFactory extends CWidgetFactory {
public function init() {
parent::init();
$this->widgets['CGridView']['cssFile'] = Yii::app()->request->baseUrl.'css/gridview.css';
}
}
You will need to adjust your components to use this file:
'components' => array(
'widgetFactory' => array(
'class' => 'MyWidgetFactory'
...

Related

CakePHP 3 make resource routes work with and without parameters

I have some code in my routes file:
Router::scope('/v1', function (RouteBuilder $routes) {
$routes->resources( 'Files');
});
And then a FilesController with a delete function like:
public function delete($id){
echo "here"; exit();
}
When I do:
DELETE http://192.168.1.197/v1/files/1
The response is here, however, if I do:
DELETE http://192.168.1.197/v1/files
The response is that it is missing the V1Controller.
What I would expect instead is for CakePHP to turn around and say "oops, you have passed the wrong number of required parameters".
Something very weird seems to be going on here and I am not quite sure what. How can I make the two do the same thing and point to the controller?
CakePHP operates very differently on exceptions when debug mode is enabled. When debug is true all exceptions are rendered with debug information, stack tracing and developer friendly messages.
When debug mode is false the exception is rendered as a standard HTTP response type. With handles for 400 and 500 error codes.
When the router can't find a match for a route there is no controller involved. The HTTP request never gets past the dispatching phase. It's the dispatcher that throws a 400 type exception.
In your given example the framework is throwing a MissingControllerException with the HTTP code of 404.
400 error codes are rendered via the ErrorController. CakePHP comes a with a default error controller, but if you generate a new application using the composer template, then you should have a default ErrorController in your app's controller holder.
In your templates there should be a src/Template/Error/error400.ctp file which displays the response for 400 codes. Keep in mind, that this template is not used when debug mode is enabled.
You can modify this template to find "closely" matching routes and offer them as recommendations to the user as feedback in the error message.
You can iterate all configured Routes easily like this:
foreach (Router::routes() as $route) {
$name = isset($route->options['_name']) ? $route->options['_name'] : $route->getName();
$output[] = [$name, $route->template, json_encode($route->defaults)];
}
Above taken from cakephp/src/Shell/RoutesShell.php:
Since this is technically a 404 error. There is no matching route and what you can do is try to find routes that are "close" to a match. The problem here is that you are subject to the same route matching challenges as the Router class.
The Router class uses dynamic routing techniques that take parts of the URL parameters and fills them in as names of controllers, names of actions and user defined parameters.
This can change significantly depending upon what kind of default router class you are using.
For example, you might be using the DashedRoute routing class which does the following:
/**
* This route class will transparently inflect the controller, action and plugin
* routing parameters, so that requesting `/my-plugin/my-controller/my-action`
* is parsed as `['plugin' => 'MyPlugin', 'controller' => 'MyController', 'action' => 'myAction']`
*/
class DashedRoute extends Route
You might instead be using the InflectedRoute routing class which does the following:
/**
* This route class will transparently inflect the controller and plugin routing
* parameters, so that requesting `/my_controller` is parsed as `['controller' => 'MyController']`
*/
class InflectedRoute extends Route
Since there are cases where routing could be using dynamic routing. It's not possible to know if a URL segment is a controller, action or named parameters.
Add to the complexity that you're also using a scoped segment named /v1 it becomes even more challenging to predict what the intended route is.
You can either create custom routes to catch these edge cases and render an informative error message, or you can try to add logic to the error400.ctp to display a more informative error message.
There is also a final option. Where CakePHP allows you to write your own custom Route classes, and/or modify the middleware with your own dispatcher.
I solved this another way entirely, just stop using the resource routes in CakePHP; I changed my code to:
$routes->get('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:get');
$routes->post('/files', ['controller' => 'Files', 'action' => 'add'], 'files:post');
$routes->put('/files/*', ['controller' => 'Files', 'action' => 'edit'], 'files:put');
$routes->patch('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:patch');
$routes->delete('/files/*', ['controller' => 'Files', 'action' => 'delete'], 'files:delete');
And it works exactly as how I wanted in the question...

No adapter set exception when setting multiple connections in li3

I am attempting to set-up multiple connections in my li3 project but when I do I get an uncaught exception. I set my connections in the app/confi/bootstrap/connections.php file which is then loaded in by the bootstrap.php file. Here is what I have for my connections:
Connections::add('default', array(
'development' => array(
'type' => 'MongoDb',
'host' => 'localhost',
'database' => 'web_app'
),
'test' => array(
'type' => 'MongoDb',
'host' => 'localhost',
'database' => 'test_web_app'
)
)
);
When I have it set like this and try to browse to my project I get this error:
Fatal error: Uncaught exception 'lithium\core\ConfigException' with message 'No adapter set for configuration in class `lithium\data\Connections`.' in /var/www/site/libraries/lithium/core/Adaptable.php:233
However when I just have a single default connection set-up it works fine. Has anyone else ran into this issue?
--UPDATE--
I went looking through the stack trace from the exception and found the issue is caused by a filter I set-up in my file app/config/bootstrap/user.php which is then loaded by bootstrap.php
Here is what my user.php file looks like:
use app\models\Users;
use lithium\security\Password;
Users::applyFilter('save', function($self, $params, $chain) {
if ($params['data']) {
$params['entity']->set($params['data']);
$params['data'] = array();
}
if (!$params['entity']->exists()) {
$params['entity']->password = Password::hash($params['entity']->password);
}
return $chain->next($self, $params, $chain);
});
According to the stack trace the error is coming from line 21 of this file. The only thing on line 21 is }); so I am still not certain why this is causing an error.
It would appear I was mislead by Li3's Simple Authentication user tutorial. In their tutorial it has you create a user.php file in the bootstrap directory and has the filter logic in this file (Exactly what I had). However it seems this is not the best way to go about it, especially when using multiple connections as it will throw the exception above. I have moved the filter logic to my Users model file in app/models/Users.php and no longer get the exception. This is the same type of setup that Gavin Davies uses in his Li3 Authentication example.

Yii2 ReflectionException Class yii\web\urlManager does not exist

I am building my website with Yii2 advanced template. The URL is rewritten into
localhost:9001/projectyii/page/index/#/demo
(page is controller, index is action, /#/demo is just a route for AngularJS on frontend)
Everything works fine on my localhost. When I upload it into my server, whenever if I hit the URL has prefix example.com/projectyii/, it will throw the following exception
ReflectionException
Class yii\web\urlManager does not exist
1. in /home/scott/public_html/projectyii/vendor/yiisoft/yii2/di/Container.php at line 415
406407408409410411412413414415416417418419420421422423424 * #return array the dependencies of the specified class.
*/
protected function getDependencies($class)
{
if (isset($this->_reflections[$class])) {
return [$this->_reflections[$class], $this->_dependencies[$class]];
}
$dependencies = [];
$reflection = new ReflectionClass($class); // error here
I notice that there are some other websites that have been running on same server already (they are all using Yii 1.1.13) and they have been working without problem, such as
example.com/project1/
example.com/project2/
...
it's just failed just this new site in Yii2.
The setting is under of components on /frontend/config/main.php is
'urlManager' => [
'class' => 'yii\web\urlManager',
'baseUrl' => $baseUrl,
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [],
]
The error told that it could not find the urlManager class, but the class does exist, the namespace is fine because I DO NOT modify anything on the vendors folder where contains that urlManager class.
I do not understand what I am missing here. Any help is appreciated! Thanks
Linux like other unix systems are case sensitive you should use:
'class' => 'yii\web\UrlManager', instead of urlManager

How to change Yii Error Handler on the fly?

In Yii's config.php we have this statement which declares which Controller is the default and only-one Error-Handler within the application:
'errorHandler' => array(
'errorAction' => 'site/error',
),
So, I need to have an actionError() under my SiteController, to get the errors previewed in my site, but this is not what I really need.
I am trying to change the Yii::app()->errorHandler->errorAction on the fly, throughout my custom-controllers who extend the base CController (Yii's base controller).
Till now, I have tried something like this:
<?php
class AdminController extends CController {
public $layout = '//layouts/admin';
public function init() {
parent::init();
Yii::app()->errorHandler->errorAction = '/admin/error';
}
}
But gives no results, nor hope. Note that I also have this URL configuration:
'/admin' => '/admin/home',
'/admin/<controller:\w+>' => '/admin/<controller>',
'/admin/<controller:\w+>/<action:\w+>/<id:\d+>' => '/admin/<controller>/<action>',
'/admin/<controller:\w+>/<action:\w+>' => '/admin/<controller>/<action>',
And this means I have a whole Controllers-Views group named admin, and they are stored in following directories:
protected/controllers/admin
protected/views/admin
So by that logic, I have ErrorController in both: admin and controllers root, and by the same structure in the views directory.
That's what I have tried, and I really appreciate help, so thank you all in advance!
You should try this :
Yii::app()->setComponents(array(
'errorHandler'=>array(
'errorAction'=>'/admin/error'
)
));
http://www.yiiframework.com/doc/api/1.1/CModule#setComponents-detail

Zend Framework 2 ViewModel returns an empty output in some modules

There are different modules and all of them returns ViewModel in the actions. But somehow, ViewModel acting weird a bit in one of the modules.
I am saying;
$view = new ViewModel(array('data' => $someContent));
$view->setTemplate('a valid path to template');
return $view;
and getting an empty page.
If I put an exit() statement at the end of related template like
<!DOCTYPE html>
<html>
...
</html>
<?php exit(); ?>
I can get the expected output because script ends there but I lost the output otherwise.
If I say *var_dump($view)*, I can see that the $view is an instance of Zend\View\Model\ViewModel.
There is no error, just an empty output and even the notice warnings are visible. So, it doesn't throw any exception, error, warning, notice etc.
To remind that again, it just happens in a specific module but that module are not different the others actually.
I am not a ZF guru and I am working on someone else's codes, so please give me a start point to able to find that problem.
Thanks in advance.
edit : I have an extra info;
It works if I use JsonModel instead of ViewModel and as you may know, JsonModel extends the ViewModel.
Since you have not posted your controller action properly , this is the guess what I could do on your problem .
In Zend framework 2 there are various types of controllers from which you will be extending your controllers with in your modules .
for example in case if you extend your controller from AbstractActionController your view will be returned properly .
So the problem here is your other modules have controllers extending AbstractActionController . This module which is not returning your view properly might not be extending it . Instead it might be extending other controllers such as restfulcontrollers
You should also check in module.php file of your module to check whether you have any strategies eg json strategy applied on bootstrap for this module from module.config.php .
eg.
return array(
'view_manager' => array(
'strategies' => array(
'ViewJsonStrategy',
),
),
)
Also you have check your module.config.php file whether you have proper specification for your viewmanager to your template .
eg .
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
Hope this helps .

Categories