Conditional extends in Blade - php

Is there any way to do a conditional #extends statement in the Blade templating language?
What I've tried:
#if(!Request::ajax())
#extends('dashboard.master')
#section('content')
#endif
<div class="jumbotron">
Hey!
</div>
#if(!Request::ajax())
#stop
#endif
Output
When the request was not AJAX it printed out #extends('dashboard.master'), but the AJAX request worked fine.
What I'm trying to do
Stop including the master template (which includes header and footer) for AJAX so it can easily display the requested content

#extends((( Request::ajax()) ? 'layouts.ajax' : 'layouts.default' ))

in the master layout:
#if(!Request::ajax())
//the master layout with #yield('content'). i.e. your current layout
#else
#yield('content')
#endif

This kind of logic should really be kept out of the template.
In your controller set the $layout property to be dashboard.master then instead of calling returning your view or response, terminate with just $this->layout->content = View::make('dashboard.template')
Take a look at the Laravel docs on this
You could end up with something like this
<?php
class Something extends BaseController {
$layout = 'dashboard.master';
public function getIndex()
{
$template = View::make('dashboard.template');
if(Request::ajax()) {
return $template;
}
$this->layout->content = $template;
}
}

Related

Laravel Blade return output of a "route name", not the URI

I have this footer inside a blade template. This footer should be displaying a variable dynamically inside the said template.
template.blade.php
<html>
<body>
#include('templates.usermenu.usermenu')
#include("templates.navigation.navigation")
#yield('header')
#yield('content')
{{ route('footer-links') }} <--this is the footer. this only outputs the "URI"
</body>
</html>
here is the output of the code above
Here is the footer.blade.php with a variable that should be displayed:
footer.blade.php
{{-- buttons --}}
#foreach ($footerLinksRecord as $record)
<div class="clearfix">
<a class="poppins-medium text-md button-white text-left float-left clickable" href="{{ $record->link }}">{{ $record->name }}
</a>
</div>
#endforeach
The footer.blade.php needs to output a variable coming from its FooterLinksController#index (the template.blade.php does not have any controller managing it).
Here is the route for the footer.blade.php and the home.index (home.index calls the template.blade.php inside its code):
Route::get('/', function () {
return view('home.index');
})->name('home');
// Footer Links Index
Route::get('/footer', [FooterLinksController::class, 'index'])->name('footer-links');
Here is the FooterLinksController#index:
public function index()
{
$footerLinksRecord = FooterLinks::all();
return $footerLinksRecord;
}
What should happen is that the footer.blade.php should output the data of its route when called, not the URI.
How should this be approached?
edit removed #include. I'm looking at the wrong code.
You could use a View Composer to handle the data for the footer view. You can include the footer where needed without worrying about the data needed for it.
You can create a new Service Provider or add to the boot method of an existing one:
public function boot()
{
...
View::composer('footer', FooterComposer::class);
}
You can use a class with a compose method to handle composing the view instead of a Controller:
class FooterComposer
{
...
public function compose($view)
{
$view->with('footerLinksRecord', FooterLinks::all());
}
}
In the layout, template.blade.php, you only have to 'include' the footer:
#include('footer')
You also have the option of making a Blade component for the footer instead.
Laravel 8.x Docs - Views - View Composers
Laravel 8.x Docs - Blade - Components

Laravel use a controller in blade

I just start to learning Laravel, I stuck in a part, I want to get data from database and pass it to a blade (view) file then use this view in another view file, and want to pass one variable to a controller but I got this error:
"Class 'adsController' not found"
web.php
Route::get('seller/panel', 'sellerController#panel');
panel.blade.php
#include('seller\hook\ads')
sellerController.php
public function panel(){
$ads = DB::table('ads')->get();
return view('hook\ads', ['ads' => $ads]);
}
adsController.php
class adsController extends Controller {
public function getStatus($p) {
if ($p == 'something') {
$status = 'yeah';
} else {
$status = 'blah blahe';
}
return view('hook\ads', $status);
}
}
ads.blade.php
<div class="ads">
#foreach ($ads as $ad)
{{ $ad->name }}
{{ adsController::getStatus($ad->approved) }}
#endforeach
</div>
So, as you see I am tring to get data from database in sellerController.php then pass it to ads.blade.php then I want to use adsController.php 's function in ads.blade.php, but it can't find adsController
Sorry I am newbie to laravel
As everyone said, it's not recommended to call the controller from the view.
Here's what I would do :
In your model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ad extends Model{
public function getStatus()
{
return $this->approved == 'something' ? 'yeah' : 'blah blaehe';
}
}
In your view :
<div class="ads">
#foreach ($ads as $ad)
{{ $ad->name }}
#include('hook.ads', ['status' => $ad->getStatus()])
#endforeach
</div>
In your controller :
public function panel(){
$ads = \App\Ad::all();
return view('hook\ads', ['ads' => $ads]);
}
At the beginning of the blade file you could include the following
#php
use App\Http\Controllers\adsController as adsController;
#endphp
then on your blade template you could use the controller as you have used here.
But it is a really bad habit to use one directly.
Since you are a newbie to Laravel change that coding practice.
You could use a service provider of a sort if you want that data which needs to be shown on a particular blade view all the time.
You should try this despite I don't recommend the approach you are trying to achieve.
{!! app('App\Http\Controllers\adsController')->getStatus($ad->approved) !!}
It should work but that's very wrong.
Most often when you get this error when your namespace declaration in the controller is wrong. Typical scenario is where you generate controller stub with Artisan and then move it somewhere else from the default location.
In some cases you need to run:
composer dumpautoload
To generate new optimized class loader map.

Laravel Views (creator & make)

I made an view called (head.blade.php) and tried to load it in HomeController __construct function with View::make() function. However, the function works, but not with the variables.
For example, here's function, with View::make():
public function __construct() {
$this->asset = new Asset;
$assets = array('core');
$css = $this->asset->generate($assets);
return View::make('includes.head')->with('styles', $css);
}
If I try to use $styles variable in view, it gives me error: (Undefined variable $styles in...-)
But, digging in Laravel docs I have found this method:
public function __construct() {
$this->asset = new Asset;
$assets = array('core');
$css = $this->asset->generate($assets);
View::creator('includes.head', function($view) use ($css) {
$view->with('styles', $css);
});
}
And the method View::creator works.
My question is, how and why the View::make() doesn't work in __construct?
PS. I'm calling the view in another view with #include method.
In general OOP, you do not return any value from a constructor. The implicit return value of a constructor is the object. Remember that the constructor is called whenever a new object is made:
$myObject = new MyObject(); // <-- I just called the MyObject constructor
Instantiation of a Laravel controller happens prior to the dispatching of the route, so returning the View inside the constructor is logically incorrect. See also this answer.
I'm not sure why you're trying to do this, but I believe it could be because you're trying to attach a 'header' view to all of the views returned by this specific controller. If so, this isn't the way you do this in Laravel. To accomplish that, make a layout view that your other views will extend:
<!-- app/views/layout/master.blade.php -->
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<article>
#include('layout.header')
#yield('content')
#include('layout.footer')
</article>
</body>
</html>
<!-- app/views/layout/header.blade.php -->
<header>
A Header
</header>
<!-- app/views/layout/footer.blade.php -->
<footer>
A Footer
</footer>
<!-- app/views/some-view.blade.php -->
#extends('layout.master')
#section('content')
View Content
#stop
With this setup, some-view.blade.php will have both a header and a footer sandwiching the view's main content.

Passing further inside of template

I'm using the same template library that phil sturgeon created and I have the following layout for my control panel. I am getting this error. I ran a var_dump on the template variable inside the control panel controller and it showed the string of the control panel view but when I do the same thing inside of the content view it says there was no body index. I would like to know how I can pass the data to the content view.
Any ideas for me?
Severity: Notice
Message: Undefined index: body
Filename: partials/content.php
Line Number: 8
Control Panel Controller
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Controlpanel extends Backend_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$this->template
->title('Control Panel')
->set_layout('controlpanel')
->set_partial('header', 'partials/header')
->set_partial('sidebar', 'partials/sidebar')
->set_partial('breadcrumbs', 'partials/breadcrumbs')
->set_partial('content', 'partials/content')
->set('user_data', $this->users_model->get($this->session->userdata('uid')))
->build('dashboard');
}
}
content.php
<div id="content">
<!-- Insert Header -->
<?php echo $template['partials']['breadcrumbs']; ?>
<div class="separator bottom"></div>
<?php echo $template['body']; ?>
</div>
I've tried looking into this and still haven't found a solution. I was hoping someone else might see something I am not.
I use his library too, and got some ploblems when passing objects through
$this->template->set('data_name', $my_object);
just cast it to array.
$this->template->set('data_name', (array) $my_object);
THe following works for me:
$this->template->set('body', $body);
Then in my view (using the PyroCMS lex parser):
{{ body }}
Alternatively, you could assign an array to the set method:
// $page is from a db query
$this->template->set('page', $page);
Then in the view:
{{ page->body }}

Modular web site with zend framework, stack of actions

How to build modular web site with Zend framework. I have pages in db, every page is represented as url. Every page has 1toN contents. Every content has controller, action and position (+other now not important columns). So, one request is one page and multiple contents (multiple actions). How can I build all actions before the output? I would like to have layout design like example bellow, where contents are put in there containers (actions are run before layout print-out).
<div id="left">
<?= $this->layout()->left_container ?>
</div>
<div id="center">
<?= $this->layout()->center_container ?>
</div>
<div id="right">
<?= $this->layout()->right_container ?>
</div>
Until now I called actions from layout view, but I do not like this approach:
foreach ($contents as $item) {
echo $this->action($item['action'], $item['controller'], null, array('content' => $item));
}
Thanks.
p.s.
adepretis's code is similar to my, views of my actions are run inside layout, which means that when error occurres it is printed in layout where the action is called. Is there no whey that actions are build before layout output? Another bad thing is that in every action I must run ...->setResponseSegment, I would like this to be automated.
p.s. #2
I have found answer, it is listed bellow as answer. If there is a whey I can do this easier please write it down.
You can use the ActionStack helper. For example:
class MyController_Action extends Zend_Controller_Action {
function init() {
/** you might not want to add to the stack if it's a XmlHttpRequest */
if(!$this->getRequest()->isXmlHttpRequest()) {
$this->_helper->actionStack('left', 'somecontroller', 'somemodule');
$this->_helper->actionStack('center', 'somecontroller', 'somemodule');
$this->_helper->actionStack('right', 'somecontroller', 'somemodule');
}
}
class MyController extends MyController_Action {
function indexAction() {
// do something
}
}
class SomecontrollerController extends MyController_Action {
function leftAction() {
// do something
$this->_helper->viewRenderer->setResponseSegment('left_container');
}
function centerAction() {
// do something
$this->_helper->viewRenderer->setResponseSegment('center_container');
}
function rightAction() {
// do something
$this->_helper->viewRenderer->setResponseSegment('right_container');
}
}
A request for /somemodule/my/index results in executing /somemodule/somecontroller/left. /somemodule/somecontroller/right, /somemodule/somecontroller/center which end up in the correspondig layout segments.
I found my answer on other forum. Here is the asnwer:
MyPlugin
class MyPlugin extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$action_stack = new Zend_Controller_Action_Helper_ActionStack();
// here I will read actions from db and run it in loop, but for example few are staticly added bellow
$action_stack->actionToStack('index', 'content', 'default', array('position' => 'left'));
$action_stack->actionToStack('index', 'content', 'default', array('position' => 'center'));
$action_stack->actionToStack('index', 'edo', 'default', array('position' => 'center'));
$action_stack->actionToStack('left', 'edo', 'default', array('position' => 'left'));
$action_stack->actionToStack('right', 'edo', 'default', array('position' => 'right'));
}
}
BaseController, that every controller extends
class BaseController extends Zend_Controller_Action
{
public function preDispatch()
{
$position = $this->_request->getParam('position', false);
if ($position) {
$this->_helper->viewRenderer->setResponseSegment($position);
}
}
}
Layout.phtml
<div>
<h2><u>LEFT:</u></h2>
<?=$this->layout()->left?>
</div>
<div>
<h2><u>CENTER:</u></h2>
<?=$this->layout()->center?>
</div>
<div>
<h2><u>RIGHT:</u></h2>
<?=$this->layout()->right?>
</div>
This is what I wanted, if anyone has a better solution please answer the question and I will accept his answer.
hi i also encounter the same problem. The solution you suggest work fine. But my baseController is in module base .The code work smooth with baseController but when i extended with controllers in another module error occure as base Controller cannot identify in other controller
For eg:
modules/ base/Controller/baseController
modules/ user/Controller/userController
Any Solutions ?

Categories