Layouts Throwing "Attempt to assign property of non-object" In Laravel 4 - php

In the Layouts folder, I have a layout called signup.blade.php
In my controller, I'm assigning a layout to it like so:
protected $layout = 'layouts.signup';
In a separate folder, named "signup" I have a file called "signup1.blade.php" It contains your typical blade template stuff. It's a section called "content". Before the code I have
#section('content')
and it's got #stop at the end.
My controller looks like this:
public function SignUp()
{
$this->layout->content = View::make('signup.signup1');
}
The frustrating part is that this is working with another layout and controller. I've double checked they're the same, and this one does not work. Any suggestions would be greatly appreciated. Thank you.

So, assuming this controller extends BaseController (it must for $layout to work), the code execution sets $this->layout to View::make($this->layout).
Your error seems to show that $this->layout is not getting set to a View object correctly.
Try to run this and see if $this->layout is an object/class, and if so, what class it is.
public function SignUp()
{
echo gettype($this->layout);
echo get_class($this->layout);
}
Knowing what $this->layout does not get changed into a View object means that the setupLayout() method is either not called or, more likely, not the result of View::make($this->layout) is not a proper view (perhaps it's silently failing for some reason).
The above steps hopefully give you a clue into whats happening there. Perhaps layouts.signup isn't a layout the app is finding?
What do your routes look like?

Change
class UsersController extends Controller
to
class UsersController extends BaseController
Hopefully the author of Confide fixes this :-)

Related

Laravel - return View::make vs $layout

Usually I have managed my layouts in Laravel like this:
views/index.blade.php
<html>
<body>
#yield('content')
</body>
</html>
views/main/root.blade.php
#extends('index')
#section('content')
<p>whatever</p>
#stop
controllers/MainController.php
class MainController extends \BaseController {
public function root(){
return View::Make('main.root');
}
}
Now I am reading about the $layout variable. The documentation says:
Your application probably uses a common layout across most of its
pages. Manually creating this layout within every controller action
can be a pain. Specifying a controller layout will make your
development much more enjoyable
But I do not see how this makes it more enjoyable.
This is the same code, but using the $layout variable:
controllers/MainController.php
class MainController extends \BaseController {
public $layout = "index";
public function root(){
$this->layout->nest('content', 'main.root');
}
}
Now, how is this easier? It seems like more code to me. Besides I have already stated that rootblade extends index so it seems like there is duplication here.
I probably am getting something wrong about this technique. Can someone help me to make sense of it to me?
If you set up your BaseController: (Laravel calls setupLayout() automatically if it exists)
class BaseController extends Controller {
protected $layout = 'layouts.master';
protected function setupLayout()
{
$this->layout = View::make($this->layout);
}
}
You can just specify the #section() name as a property, not have to #extend() your views. and / or override the layout inherited form BaseController.
class MainController extends \BaseController {
public function index(){
$this->layout->content = View::make('main.index');
}
}
In your view:
#section('content')
<div class="row-fluid">
Test
</div>
#stop
In the master layout:
#yield('content')
The point is
not having to specify #extends in every single view
The possibility to render the content section of a template individually, for example for an AJAX template or to re-use the content section in more than one layouts.
Whether or not it is actually good practice or if it saves you any pain is definitely arguable, but that's the idea behind it.
I have been asking on IRC and it seems like this is actually coming from Laravel 3, and now #extends is the new way of doing things. So it appears setupLayout is sort of legacy code. So I guess I can safely ignore it.

Defining global variable in laravel

Model: Comment.php
class Comment extends Eloquent {
protected $table = 'comments';
public $timestamps = true;
}
Controller: PageController.php
class PageController extends BaseController {
$top_comments = Comment::take(3)->get();
return View::make('page', array('top_comments' => $top_comments));
}
View: page.blade.php
#foreach ($top_comments as $comment)
user #{{ $comment->user_id }}:<br />
{{ $comment->comment}}
#endforeach
This works perfect with the page.blade.php view which I can define as a route (/page). However, I can't seem to figure out how to achieve this globally.
Example: I want to be able to use the #foreach containing $top_comments in my master.blade.php file. Right now if I was to use the above, it works great on /page but not on /, /about, /tos
You can use View::share('top_comments', Comment::take(3)->get()); to make it available everywhere. Of course, you'll have to place it some place where it gets loaded no matter what page you load if you want it in every possible view. (One such place would be in the __construct() method of your BaseController, but I doubt that could be considered a best practice. Not sure where I'd put it myself.)
Another way would be to leverage view composers, like this:
View::composer('master', function($view)
{
$view->with('top_comments', Comment::take(3)->get());
});
This works if you meant that you want it in your master.blade.php no matter from where it is loaded, because it's bound to that view. If you choose this option, I recommend for instance creating a file composers.php and including that in app/start/global.php.
That said, I assume your controller sample above left something out, because it looks like it's missing a method declaration.

Laravel how to include a partial in the base controller

In my laravel application I am using a Base_Controller class and then extend this class in other controller.
In my app there is a variable which I need to use in all my controller and templates.
This is why I tried to use in my base controller.
$this->layout->myVar = 'stuff'
But when I try use $myVar in my view I am getting an error:
Creating default object from empty value
My base class constructor is something like this:
public function __constructor()
{
parent::__construct();
$this->layout->menu = 'stuff';
}
Does anyone have any idea on what is the best way to approach this?
You must have $this->layout defined in your controller class or else $this->layout must be assigned an instance of View::make().
$this->layout->menu may also require having the #section('menu') #endsection in it.

Zend framework, View

Small mystery: can't seem to pass views between my Index controller (chartAction) and my view. When I go to my localhost it is not accessing the view phtml- instead it is just showing the controller every time (i.e: if I write "echo "HELLO WORLD!""; in my controller I get that echoed...but if I do a $this->view->test = "Hello World!" then access the index.phtml and type in echo $this->test; I get nothing (it still defaults to the controller action). Is there a step that I'm missing here? Why is my $this->view not functioning? I used the command line to create the view so I'm pretty sure that should be set up correctly.
Do I need to register something? Thanks for any help!
Assuming a standard MVC setup of ZF1.x, there is a definite relationship between the url, the controller and the action.
The url http://mydomain.com/index would call the index action of the index controller, typically the index action is the default action and is called automatically. the view script would be /application/views/scripts/index/index.phtml
The url http://mydomain.com/index/chart would call the chart action of the index controller and the view script would be /application/views/scripts/index/chart.phtml
Keep in mind that this behavior is changeable based on configuration and routing options.
It sounds like you may be fairly new at working with ZF. So something like the following may help demonstrate the relationship :
// application/controllers/IndexController.php
class IndexController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$this->view->test = "Hello World, from the indexAction().";
}
public function chartAction()
{
$this->view->test = "Hello World, from the chartAction().";
}
// application/views/scripts/index/index.phtml
<?php echo $this->test ?>
// application/views/scripts/index/chart.phtml
<?php echo $this->test ?>
now test your application by calling the url's:
http://yourDomain.com/index/index
http://yourDomain.com/index/chart
If your setup is correct you will see the proper response in your pages.
Case 1: View disabled for just one action:
Look for the following code in your action.
$this->_helper->viewRenderer->setNoRender(true);
Case 2: View disabled for all actions in a specific controller:
Look for the above line in either the init() or preDispatch() functions of the controller.
Case 3: View disabled for all actions in all controllers:
Check case 1 and 2. Also, look for something like the following in your Bootstrap.php:
$frontController->setParam("noViewRenderer", true);
If you find the code like above, you will have to comment it out to get the view working. I am sure there are more possibilities to disable view. Those are to be checked after this.
Your view is disabled..check these lines of code in your action or init of your controller or even the class your controller may be extending
$this->_helper->layout->disableLayout();
$this->_helper->viewRenderer->setNoRender();
UPDATE
You are doing it in your chartAction and echoing in your index.phtml you must do that in your chart.phtml

CakePHP - Problems with ErrorHandler not extending AppController

I had been wondering why my error page caused certain pages of my site
not to render, but then I realized that it's because AppError extends
ErrorHandler instead of AppController. This caused some variables
that I set in AppController's beforeFilter method not to be sent to
the view. Since I can't access session variables from AppError, I
thought that I might be able to get away with using the classRegistry
to instantiate something that could and simply copying and pasting the
rest of my code from AppController's beforeFilter... but that isn't working, nor does it seem like a very elegant fix. Does anyone have any clues as to what
would be the best way to approach this? Thanks, David.
Your AppError class has a controller instance. You can call the beforeFilter manually:
<?php
class AppError extends ErrorHandler {
function error404() {
$this->controller->beforeFilter();
parent::error404();
}
}
?>
In CakePHP 2, you can do something like this to achieve the same effect. In app/Config/bootstrap.php, add this line:
Configure::write('Exception.renderer', 'AppExceptionRenderer');
Then create a file app/Lib/Error/AppExceptionRenderer.php with this code:
App::uses('ExceptionRenderer', 'Error');
class AppExceptionRenderer extends ExceptionRenderer {
protected function _outputMessage($template) {
$this->controller->beforeFilter();
$this->controller->render($template);
$this->controller->afterFilter();
$this->controller->response->send();
}
}
Described more generally here: http://book.cakephp.org/2.0/en/development/exceptions.html#using-a-custom-renderer-with-exception-renderer-to-handle-application-exceptions
Edit: Updated link to point to correct location of the CakePHP 2.0 Book as of July 05, 2012.

Categories