Laravel use a controller in blade - php

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.

Related

Passing data from view to Layout in Codeigniter 4

I'm brand new to CodeIgniter, so apologies if I'm missing something obvious here.
I'm comfortable with sending data from a controller to a view file using return view('default/blog/index', $data);. My issue is accessing the same data in a layout file which is extended by the view file using <?= $this->extend('layouts/default'); ?>.
For example, if I insert <?= $data['content'] ?> in my view file, it displays as expected. If I insert the same code in the layout file that is extended by my view file, I get the "Trying to access array offset on value of type null" exception.
What am I missing that will allow me to access my data from within the layout file?
Thanks in advance.
Update:
So in my BlogController I've got
class BlogController extends BaseController
{
public function index()
{
$model = new Blog();
$data = $model->getBlog();
return view('default/blog/index', ['data' => $data]);
}
public function item($slug = null){
$model = new Blog();
$data = $model->getBlog($slug);
return view('default/blog/item', ['data' => $data]);
}
}
And then in my item.php and index.php files, I have
<?= $this->extend('layouts/default', ['data' => $data]); ?>
My Blog Model's getBlog() method:
public function getBlog($slug = false)
{
if ($slug === false) {
return $this->orderBy('bs_created_dt', 'desc')->findAll();
}
return $this->where(['bs_slug' => $slug])->first();
}
When I use the debug toolbar to inspect the data, it is showing as expected, and I can display it in the view files, but not in the layout file.
In Codeigniter, you need to pass data also in an extended file called layouts.
Because you want to access data inside the extended file and for that, you just need to pass data to that file.
So replace the line of code of extended view with this :
$this->extend('layouts/default', ['data' => $data]);
Figured this out - absolute rookie mistake.
I'm working off of a pre-existing template, and the previous developer had overwritten the $data variable in layout file before where I was trying to use it.
I'm off to stand in the corner for a while.

enum class in ternary expression

Enums were introduced to PHP very recently. I'm trying them out in a laravel project. I've got my enum class here:
namespace App\Enums;
enum AlertType
{
case SUCCESS;
case ERROR;
}
I'm trying to create an alert class that will take the enum in the constructor to set the severity of the alert, which will decide what colour it is rendered as to the user. Here is that class:
<?php
namespace App\View\Components;
use App\Enums\AlertType;
use Illuminate\View\Component;
class Alert extends Component
{
public string $contextClass;
public function __construct(public string $message, AlertType $alertType = AlertType::SUCCESS)
{
$this->setContextClassFromAlertType($alertType);
}
public function setContextClassFromAlertType(AlertType $alertType)
{
$this->contextClass = ($alertType === AlertType::SUCCESS ? 'success' : 'error');
}
public function getClassListFromType()
{
return [
'border-' . $this->contextClass,
'text-' . $this->contextClass
];
}
public function render()
{
return view('components.alert', [
'class' => implode(' ', $this->getClassListFromType())
]);
}
}
This alert will be used in a login form which is built using Laravel Livewire and blade components:
<form class="grid grid-cols-min-auto-1 gap-x-2" id="login" action="/login" method="post">
<x-alert :message="$errorMessage"/>
#csrf
<label for="email" class="mb-2 text-lg text-sans w-min mt-2 font-thin">Email</label>
<x-basic-input wire:model="email" placeholder="{{ $emailPlaceholder }}"/>
<label for="password" class="mb-2 text-lg text-sans w-min mt-2 font-thin">Password</label>
<x-basic-input wire:model="password"/>
</form>
When I come to display the login form I am getting the following error:
Cannot instantiate enum App\Enums\AlertType (View: /resources/views/livewire/forms/login.blade.php)
I think there is something wrong with my enum usage in the Alert component, but I'm not sure where. Can anyone point me in the right direction. I've looked at the rfc for enums but I can't see anything obvious that I'm doing wrong
I was able to reproduce this error; in my case the stack trace led back to the barryvdh/laravel-debugbar package, not sure if this is the same for you. I was able to resolve it by changing the enum to a backed enum.
I'd recommend making this change regardless, as I expect in a lot of cases strings will be easier to work with than enum instances. (Though TBH this looks like trying to use a new feature just because it's there, not because it makes sense.)
namespace App\Enums;
enum AlertType: string
{
case SUCCESS = 'success';
case ERROR = 'error';
case INFO = 'info';
}
In a backed enum, each item has a string representation that can be accessed using the value property, which we do in the constructor:
<?php
namespace App\View\Components;
use App\Enums\AlertType;
use Illuminate\View\Component;
class Alert extends Component
{
public string $contextClass;
public function __construct(
public string $message,
AlertType $alertType = AlertType::SUCCESS,
)
{
$this->contextClass = $alertType->value;
}
public function getClassListFromType()
{
return [
'border-' . $this->contextClass,
'text-' . $this->contextClass
];
}
public function render()
{
return view('components.alert', [
'class' => implode(' ', $this->getClassListFromType())
]);
}
}
You're now able to use the from() or tryFrom() methods which can add flexibility with alert types saved in a variable. For example:
<x-alert :message="$errorMessage" :type="App\Enums\AlertType::from($errorType)"/>
I think the problem here is due to dependency injection. In the constructor I'm typehinting an enum, so the Laravel container is trying to create an instance of that class to pass in which doesn't work because enums are instantiable.
If I update the container to manually resolve the typehinted instance like this:
$this->app->bind(Alert::class, function ($app) {
return new Alert('this is a message', AlertType::SUCCESS);
});
Then the issue is resolved and it works as expected. I'll need to change the way I'm using enums here as #miken32 suggests to use a backed enum and rely on the strings instead. Otherwise I'd need to override the container injection for every method where I wanted to pass an enum.

Cannot display the variable in the blade template from the controller

I cannot figure out how to display the route name in the blade template of laravel. Please find below the sample code. Thank you.
from the controller (StaffsController.php)
public function index()
{
$thisRoute = Route::current()->uri();
return view('staff.list')>with(compact('thisRoute'));
}
Blade:
{{ $thisRoute }}
This is the var_dump
/home/vagrant/Code/spark/app/Http/Controllers/StaffsController.php:20:string 'staffs' (length=6)
Error:
(1/1) UnexpectedValueException
The Response content must be a string or object implementing __toString(), "boolean" given.
When i change the code in the controller to:
public function index()
{
$thisRoute = Route::current()->uri();
return dd($thisRoute);
}
I get "staffs" as output which is correct which is a string from the dump, right?
change your return statement to be like this :
return view('staff.list', compact('thisRoute'));
if you are using laravel 5.3 or above you can get route name like this:
Route::currentRouteName();
with this, you really don't have to passe it from your controller to the view just use it directly from your blade view :
{{ Route::currentRouteName() }}
Sorry guys, I solved the issue. I missed - in the line
return view('staff.list')>with(compact('thisRoute'));
Changed it to
return view('staff.list')->with(compact('thisRoute'));
I made a mistake.
Thank you

Symfony2 controller navbar

i would put a controller for my navbar and i would use a query to get a variable from my database..
I don't have a controller and i create it in this way:
<?php
namespace Dt\EcBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class NavbarController extends Controller {
public function navbarAction(Request $request) {
$prova = "ciao";
return $this->render('DtEcBundle:Header:navbar.html.twig',array(
"prova" => $prova,
));
}
}
Now i put my render controller in the body of : "{# app/Resources/views/base.html.twig #}"
{{ render(controller('DtEcBundle:Navbar:navbar', { 'prova': prova })) }}
I follow this but i don t understand the error: "http://symfony.com/doc/current/book/templating.html#embedding-controllers"
I Get this error Variable "prova" does not exist in DtEcBundle:Header:navbar.html.twig at line 5 but if i write the code in navbar.html.twig give me equals error..
If i remove the variable and i write only
{{ render(controller('DtEcBundle:Navbar:navbar')) }}
Give me a server error number 500 o.o..
How can i do for use my controller only in navbar.html.twig??
navbarAction doesn't take prova variable as a parameter, so why are you passing it there in a base template?
I think that action should fetch these data from db.
In that case, using:
{{ render(controller('DtEcBundle:Navbar:navbar')) }}
seems to be ok, and error is somewhere else.
If you get a 500, check logs to tell us what's exactly wrong.
And format your code, it's barely readable.
The error is the code:
{{ render(controller('DtEcBundle:Navbar:navbar', { 'prova': prova })) }}
the prova variable doesn't exists in twig, the controller is fine.
I if you want put the var from twig to controller:
/**
* #Route("/prova/{prova}", name="prova")
*/
public function navbarAction(Request $request,$prova) {
return $this->render('DtEcBundle:Header:navbar.html.twig',array(
"prova" => $prova,
));
}
and twig:
{% set prova = 'foo' %}
{{ render(controller('DtEcBundle:Navbar:navbar', { 'prova': prova })) }}

Conditional extends in Blade

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;
}
}

Categories