In my BaseController I have this:
public function __construct()
{
$user = Auth::user();
View::share('user', $user);
}
I can access the $user array throughout all of my views but what if I want it to be a global variable available in all of my Controllers?
I have the following working code:
use Auth;
use DB;
class UsersController extends BaseController
{
public function index()
{
$user = Auth::user();
$users = DB::table('users')->where('user_id', $user->user_id)->get();
return view('pages.users.index', compact('users');
}
}
I want the $user variable available in all of my controllers and within all of the public functions within each on the controllers but I don't want to have to redeclare "use Auth;" and "$user = Auth::user();"
I tried adding it to a __construct in the BaseController but that didn't seem to work, Undefined $user variable error. Any thoughts? I know it's possible.
Has shown in other answers, you can:
set it as a property of your base controller (I don't recommend this, it just adds clutter)
create a custom helper (see below)
just do \Auth::user()
Another technique, you can use auth() helper:
auth()->user()
It is even documented.
According to this PR, there is no plan to add an user() helper in Laravel.
If you consider it is worth adding this helper to your project, here is the code:
function user()
{
// short and sweet
return auth()->user();
// alternative, saves one function call!!
return app('Illuminate\Contracts\Auth\Guard')->user();
}
I do not see why something like this would not work:
public function __construct()
{
$this->user = \Auth::user();
\View::share('user', $this->user);
}
This way it's available to all your views and as long as your controllers are extending BaseController, it's available in all your controllers as well with $this->user.
Why don't you use a helper function. It won't give you a $user variable, but it can give you a more cleaner way to accomplish this.
In your helpers.php add a function:
function getUser(){
return Auth::user();
}
In all other places (controller, views, models) call: getUser(). That's it.
If you don't have any helper file for your functions yet. You can follow this link to create one.
I don't see whats the issue with using Auth::user(), this class is using singleton pattern which means that if the Auth::user() is already initialized it won't check again against the database especially when most of the code shouldn't even be inside a controller so basically you would still need to do Auth::user() inside your services, models, form requests, etc..
abstract class Controller extends BaseController {
protected $user;
use ValidatesRequests;
public function ___construct(){
$this->user = \Auth::user();
}
}
Related
I have laravel 5.6 project
and I have registered middleware called permissions. I need to assign this middleware in a controller, but not for the whole controller- just for one function without using __construct().
I mean I want to assign this in:
public function index()
{
$this->middleware('permission');
}
I've tried it like this, but its not working. It's worked when I use it inside:
public function __construct()
{
$this->middleware('permission');
}
But I don't need it like that.
Thanks.
Middleware can only be registered in the constructor. You can use the only() method though, like:
function __construct()
{
$this->middleware('permission')->only('index');
}
I believe you can pass an array of middlewares as well. There's also the except() method that does the opposite.
Here is your solution:
public function __construct()
{
$this->middleware('permission')->only('index');
}
I'm new in Laravel, I want to know where is the correct place where define functions that query table from DB. In Model or in Controller?
Example:
public function insertUser($firstname, $lastname, $email) {
$user = new User();
$user->firstname = $firstname;
$user->lastname = $lastname;
$user->email = $email;
$user->save();
return $user;
}
The function above where I should declare? Models or Controllers?
Edit:
For example: I need to create a function that return male authors that live in USA and their books. I define AuthorController that use Author (Model). What's the right way to define this function? I write a function in my controller that accept gender and nation as arguments, like:
public function getAuthoursByGenderAndNation($gender, $nation) {
$authors = Author::with("books")->where("gender", "=", $gender)->where("nation", "=", $nation)->get();
return $authors;
}
Or I define a generic function that returns all authors with their books and then apply where clause on function that call this generic function? Like:
public function showAuthors(Request $request) {
$gender = $request->get("gender");
$nation = $request->get("nation");
$authors = $this->getAuthors()->where("gender", "=", $gender)->where("nation", "=", $nation)->get();
return view("authors", ["authors" => $authors]);
}
public function getAuthors() {
$authors = Author::with("books");
return $authors;
}
keep in mind that all application logics should be in controller, and all data operations should be in model. in your question insert user is a application logic, so you should place that on controller, but if you want to define how data is managed, place that method in model. For example, you want a model has ability to retrieve a collection with some condition, may be a user with female gender only so you can Access it via Modell::getFemale()
The function you mention, should be used within a controller. I would recommend that you get a grasp on how MVC works before you dive in Laravel.
Reading that may be useful to you
MVC Concept
Laravel Docs
PHP MVC Tutorial
As according to MCV recommendations.
M (model) should be fat and C (controller) should be thin.
you should write your all database transaction related code in model. Even you can create repositories for database queries.
Your controller should be thin, so you should write only logical code there, like calling model function.
Example:
UserController.php
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Requests\Request;
class UserController extent Controller {
use App\User;
protected $_user;
public function __construct(User $user) {
$this->_user= $user;
}
function saveUser(Request $request) {
$user->fill($request->all());
$user->save();
// or you can directly save by $user->create($request->all());
}
}
This is how you can directly fill data to your User model with $fillable attribute defined there as
$fillable= ['name','email','password'];
If you define your model under the conventions of Eloquent you can simply use the built in Eloquent methods to insert your user as demonstrated in the documentation.
https://laravel.com/docs/5.3/eloquent#inserting-and-updating-models
In the wider scope of your question: 'where to define functions that query the DB table'.
I would suggest typically defining these on the model and looking to make use of the structures provided by Eloquent, for example defining scoped queries on your model.
The code in your controller would then call methods on your model eg.
Model::create();
It also appears you are trying to insert users. I would strongly suggest you look into using Laravel's built in Authentication structures. You'll find these very powerful.
https://laravel.com/docs/5.3/authentication
Hope this helps get you started.
I think we have separate controllers respective to separate logic or modules of our application, and i have also found that using a controller inside another controller is not a good practice.
Here i have facing a difficulty.
there are two controllers PagesController and PostsController
PagesController handle all pages related tasks.
class PagesController
{
public function index()
{
// method of our root request, get and show all posts
}
public function contactUs()
{
// show contact us page etc.
}
}
PostsController handle all posts related tasks.
class PostsController
{
public function getPosts() {} // get all posts from database
public function deletePost($id) {} // delete a post
public function editPost($id) {} // edit a post
}
Now post controller handle all posts specific tasks and pages controller handle all pages related tasks. The problem is that i want to use posts controller getPosts() method to get all posts and pass them to view. How can i use PostsController's getPosts() method inside our PagesController index() method.
One way is extends PostsController and use it. But what if we want to use another controller's method also.
Please provide me better way to do that.
https://www.youtube.com/watch?v=MF0jFKvS4SI
This talk is a bit advance about controllers but it is surely a good practice regarding controllers.
better to create a trait......
How to use traits in Laravel 5.4.18?
You can use XyzController method in any controller by following way
use App\Http\Controllers\XyzController ;
class AnyController extends Controller {
public function functionName()
{
$result = (new XyzController)->methodName();
// this will call method of XyzController
}
}
Hope this will help.
Your controller should not have any logic. Create a service or create a method in Repository and move PostsController's getPosts()'s code into this method. And then call this new method in both PostsController and PageController.
The whole point of having Repository is for this purpose.
I usually prefer Repository pattern to get task done.
Here's an Overview.
interface BaseMethodsForRepository {
/**
* #return mixed
*/
public function get();
//other base methods like store (handle create/update in common method) and delete.
}
class PostRepository implements BaseMethodsForRepository {
public function get() {
return Post::all();
}
//Many more methods
}
class PagesRepository implements BaseMethodsForRepository {
public function get(){
return Page::all();
}
}
class PageController {
private $postRepository
public function __construct(PostRepository $postRepository) {
$this->postRepository = $postRepository;
}
public function index(){
//here you can use all public methods of PostRepository
//usage
$post = $this->postRepository->get();
}
}
I found this useful and code is reusable.
This question already has answers here:
Laravel 5.3 auth check in constructor returning false
(3 answers)
Closed 6 years ago.
Im working on an app in Laravel 5.3. I have created an AppController. I would like for all of my controllers to extend AppController so that they all share a few common properties and methods.
Given the below 2 implementations below, my intention is to set the current user to $this->user when AppController is constructed so it will be available to all controllers extending AppController.
I expect that when I call \App\Http\Controllers\User\PermissionController#test I should get my user object dumped twice. Once when AppController is initialized, and again when PermissionController#test is called.
However, inside of AppController __construct(), $this->user is always NULL while PermissionController#test dumps the user as expected.
AppController:
<?php
namespace App\Http\Controllers\App;
use App\Http\Controllers\Controller;
class AppController extends Controller
{
/**
* The current user when logged in
* #var \User
*/
protected $user;
public function __construct()
{
if(\Auth::check() ) {
$this->user = \Auth::user();
}
var_dump($this->user);
}
}
PermissionController:
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\App\AppController;
class PermissionController extends AppController
{
public function test()
{
if(\Auth::check() ) {
// Do something
$this->user = \Auth::user() ;
}
var_dump($this->user);
}
}
If it matters, I'm using https://github.com/Adldap2/Adldap2-Laravel to auth against Active Directory.
Clearly I'm misunderstanding something hear. Why does AppController __construct() not dump the user?
This is because of changes in Laravel 5.3. If you need to use Auth in constructor you need to do it like so:
public function __construct()
{
$this->middleware(function ($request, $next) {
if(\Auth::check() ) {
$this->user = \Auth::user();
}
var_dump($this->user);
return $next($request);
});
}
This change was described in upgrade guide to Laravel 5.3 - https://laravel.com/docs/5.3/upgrade#upgrade-5.3.0 look at section Session In The Constructor
Please check my answer here.
You need to move this check in middleware if you're using Laravel 5.3
The controller construct executes before any middleware, so there is no user yet (https://laravel.com/docs/5.3/upgrade#upgrade-5.3.0)
You can use closure middleware as described in the guideline.
From the docs
In previous versions of Laravel, you could access session variables or
the authenticated user in your controller's constructor. This was
never intended to be an explicit feature of the framework. In Laravel
5.3, you can't access the session or authenticated user in your controller's constructor because the middleware has not run yet
As an alternative, you may define a Closure based middleware directly in your controller's constructor. Before using this feature, make sure that your application is running Laravel 5.3.4 or above:
public function __construct()
{
$this->middleware(function ($request, $next) {
$this->user = auth()->user();
return $next($request);
});
}
I have Content controller with REST methods (index..create..store..) and i want to run some code before any of those methods run.
what i am trying to do is to set var for my layout with some data that is relevant to all my methods within Content controller:
$this->layout->myvar = 'some-data';
I tried to do something like that:
class ContentController extends BaseController {
function __construct() {
$this->layout->myvar= 'some-data';
}
..
but it doesn't seems to work.
i get "Attempt to assign property of non-object" error.
Laravel 5.1+
This has been deprecated in favour of Middleware.
Laravel 4
You could set the beforeFilter like this:
class ContentController extends BaseController {
function __construct() {
// this function will run before every action in the controller
$this->beforeFilter(function()
{
// this will make the variable $myvar available in your view
$this->layout->with('myvar', 'some-data');
});
}
}
try share in app/routes.php
View::share('variable_name', 'value');
ex:
View::share('name', 'Steve');
will share variable with its value across all views