Laravel, calling controller method from blade template file - php

Heey guys! I use Laravel 5.4, WAMP for localhost. I am struggling with the problem to call a Controller#methodName within my header.blade.php file, because I want to show in my header.blade.php file all notifications for the User. Normally I was getting all needed data with the help of routes in different pages. But for this case I need to call without using routes. Here is my code for my NotificationController:
class NotificationController extends Controller
{
public function getNotification(){
$notifications = Notification::where('user_id',Auth::user()->id)->get();
$unread=0;
foreach($notifications as $notify){
if($notify->seen==0)$unread++;
}
return ['notifications'=>$notifications, 'unread'=>$unread];
}
}
And I should receive all these data in my header file. I have used: {{App::make("NotificationController")->getNotification()}}
and {{NotificationController::getNotification() }} But it says Class NotificationController does not exist. Please heelp!

Instead of calling the controller method to get notifications, you can make a relationship method in your User model to retrieve all the notifications that belongs to the user and can use Auth::user()->notifications. For example:
// In User Model
public function notifications()
{
// Import Notification Model at the top, i.e:
// use App\Notification;
return $this->hasMany(Notification::class)
}
In your view you can now use something like this:
#foreach(auth()->user()->notifications as $notification)
// ...
#endforeach
Regarding your current problem, you need to use fully qualified namespace to make the controller instance, for example:
app(App\Http\Controllers\NotificationController::class)->getNotification()

Try using the full namespace:
For instance, App\Http\Controllers\NotificationController::getNotification
but of course, controllers aren't meant to be called the way you're using them. They're meant for routes. The better solution is to add a relationship in your user model like so:
public function notifications()
{
return $this->hasMany(Notification::class)
}
And then use this in your view like so:
#foreach(Auth::user()->notifications as $notification)

Related

refer variable from controller to all blade Laravel 5

I've code in my controller which returns some $data, and I want to refer that in all my blades, I can make routes for each page, but I don't like this way. I thought should be better if I refer this $data on layout.blade which include navbar, and etc..., but is it a possible to make route without url? cause I don't want to appear my layout.blade, So my question is, what is a best way to get $data on each blade?
You may perhaps want a view composer. A view composer is an extension of a blade via php that runs before the blade.
In app service provider you set the view you want to view composer class.
use Illuminate\Support\Facades\View;
use App\Http\ViewComposers\LayoutComposer;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
View::composer('layout', LayoutComposer::class);
}
}
Then write your logic in the class.
use Illuminate\View\View;
class LayoutComposer
{
public function compose(View $view)
{
$data = Model::where('id',###)->first();
return $view->with(['data' => $data]);
}
}
https://laravel.com/docs/7.x/views#view-composers

Middleware to convert IDs to slug

I've got 90% of my site finished, up until now it's been passing round model IDs from page to page as such:
http://website.domain/2/content/3
I'm using models bound within the web.php like so:
Route::get('{post}/content/{comment}', 'ContentController#index');
This is working fine.
I would like to change the URL so it's more user/SEO friendly so it displays as such:
http://website.domain/hello-world/content/this-is-more
I know I can do a look-up in the controller for every index, however I was wondering if there was a more automated way to convert the URL when an ID is used, such as a middleware perhaps, or is doing a look-up everytime I need to do it the only way forward?
Any help would be appreciated.
You dont need to do that through middleware...
The Eloquent's models has a method that indicates what column will be used by the router to lookup the binded model, you just need to override it.
Example for the post's model:
namespace App\Models\Post;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Route;
class Post extends Model
{
public function getRouteKeyName(): string {
$identifier = Route::current()->parameters()['post'];
if (!ctype_digit($identifier)) {
return 'your-slug-col-name';
}
return 'id';
}
}
This way your route will work with id or slug...
One easy way is use explicit model binding
in app/Providers/RouteServiceProvider.php in method boot you can define your bindings
For ex:
public function boot()
{
Route::bind('postSlug',function($value){
return Post::whereSlug($value)->firstOrFail();
});
Route::bind('commentSlug',function($value){
return Comment::whereSlug($value)->firstOrFail();
});
parent::boot();
}
and in your Route.php:
Route::get('{postSlug}/content/{commentSlug}', 'ContentController#index');
hope this is helpful

Load user settings with Laravel 5.6

I'd like to be able to modify the Auth->user() data that Laravel 5.6 uses. I have table called settings with a column called user_id in it that corresponds to a user id.
I tried modifying app\User.php and adding a __construct function:
public function __construct() {
$this->settings = Settings::where('user_id',
Auth->user->id()
)->first();
}
And I created a file app\Settings.php with the following:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class settings extends Model
{
protected $table = "settings";
}
However I'm getting a user error on the Auth->user()->id line in User.php, although I'm sure thats the correct way to reference it?
How can I load the data from the settings table to the User class?
You can just use load() method to lazy load the relation:
auth()->user()->load('settings');
You need to do this just once per request, in a middleware for example. Then you'll be able to use the data in any part of your app:
{{ auth()->user()->settings->theme }}
Of course, to make this work you need to define relationship in the User model, for example:
public function settings()
{
return $this->hasOne(Settings::class);
}

Laravel place query inside of controller or model class

#1
Class controller {
$customer = Model\customer::find($id);
}
#2
Class controller {
$customer = new Model\customer;
$customer = $customer->data($id);
}
Class Model {
public function data($id) {
return self::find($id);
}
}
I'm new in larava, I got a question about MVC query.
I saw many people put query inside of controller like #1
I usually like to put query inside of model class.
any suggestion?
According to me MVC means - Model View Controller.
In a general language Model should contain the Database Query related stuffs whereas in View you should always use variables to populate view data and at last Controller is generally for catching the requests and send the response by doing some logical functionality on request.
<?php
namespace App\Models;
class ExampleModel
{
// All the database related methods like - all, paginate, find, where, etc would goes in the model...
}
In case of Views
<html>
...
YOUR_CONTENT_HERE
...
</html>
and in case of Controller,
<?php
namespace App\Controllers;
class ExampleController
{
public function index()
{
$request = request()->all();
... do some logical work here ...
return response($data);
}
}
Thats what MVC code structure would be like - in my opinion
Hope this helps!
It's ok to use the model's find() method directly to retrieve an entity.
If you are developing a larger application, you should, however, consider moving all the logic into your own classes. The controller should just collect the input from the http request, session etc. and call a method on a service to do the actual work. That way your code is not glued to a controller action or route.

Using multiple controllers inside of one view

I Need some advice, as I'm still a bit new to Laravel and MVC in general. I'm coding a small web application that presents some data on the page, fetched from a remote API. However, the page already has a controller to it. The other controller I will be using I'm hoping I can also reuse it for other pages. I'm pretty stuck here.
So the two controllers
HomeController.php
ApiController.php
The HomeController is the original controller, which gets the view file (home.blade.php), with some other data that's being loaded from the controller.
With the ApiController, I want to fetch the api (json) results, do some changes and then load those changes to the HomeController as well. The changes would be like an array of methods and such that's being loaded to the view.
So How can I load both controllers inside of the same view?
First of all controllers doesn't get loaded inside view instead, you should load a view from a controller and to make the remote request for an API call you don't need to use another controller but you may use it if you have other use of API and need a separate controller. The flow is something like this:
class HomeController extends BaseController {
public function index()
{
// make the api call/remote request
// modify the returned data
// load the view
}
}
Let's rewrite it:
class HomeController extends BaseController {
protected $apiService = null;
public function __construct(ApiService $apiService)
{
$this->apiService = $apiService;
}
public function index()
{
// make the api call/remote request
$apiData = $this->apiService->makeRequest();
// modify the returned data.... then...
// load the view
return View::make(...)->with('apiData', $apiData);
}
}
So, it seems clear that, you should use the API related process in a separate class as a service, maybe a model or a simple repository class and inject it to your HomeController then use it from the controller.
Do all the API stuffs in ApiService and call methods of that class from the HomeController, in this case you may implement the ApiServiceRepository as a concrete class by implementing an interface, i.e. ApiService. So, finally it could be like this:
interface ApiService {
public function makeRequest();
}
// Implement the interface in concrete class
class ApiServiceRepository implements ApiService {
public function makeRequest()
{
// $data = make remote request
// return $data
}
}
Use the class HomeController with __construct as given above and add a IoC binding like:
App::bind('ApiService', 'ApiServiceRepository');
So, you don't have to worry about the dependency injection in the constructor of your HomeController.
BTW, to use a method from another controller, for example ApiController from HomeController you may use something like this:
$apiController = App::make('ApiController');
// Call any method of "ApiController" class/object
$apidata = $apiController->makeCallToMethod();
You may also check this article for understanding the use of repository pattern in Laravel.

Categories