Call controller function in another controller - php

I've a PermissionController with a permission() function like below, and i want to call the permission() function in another controller. How can i call my permission() function to another controller ?
here my PermissionController
class PermissionController extends Controller
{
public function permission(){
$checkPermission = User::leftJoin('employees', 'employees.user_id', '=', 'users.id')
->leftJoin('positions', 'employees.position_id', '=', 'positions.id')
->leftJoin('divisions', 'employees.division_id', '=', 'divisions.id')
->where(function($query){
$query->where('division_name', 'Sales')
->orWhere('division_name', '=', 'Project Management')
->orWhere('position_name', '=', 'Dept Head');
})
->get();
}
}

Create new Helper (e.g PermissionHelper.php) then move the funtion to it and call it where you want using :
PermissionHelper::permission();
Hope this helps.

You can call another controller's method, but this is terrible practice. Move you code to a model and call it with:
class PermissionController extends Controller
{
public function permission()
{
$checkPermission = User::getEmployeePermissions();
}
}
Do the same in other controllers' methods.

I think your function should be in one of your model since you're only getting value.
This will me more relevant according to MVC.
Having it in your User model will let you use it on every instance of your application with a single call.

You can call your PermissionController's "permission" method this way :
app(PermissionController::class)->permission();
However, be aware that this method isn't a good idea at all.
You have multiple refactoring options available ranging from the use of a helper class, a method on the concerned model or using a laravel job.

Try to do like this
public function __construct(PermissionController $permission_controller)
{
parent::__construct();
$this->permission_controller = $permission_controller;
}
Call any method like this
$this->permission_controller->permission();

Related

Laravel 5.2.3 repeated part of code in several controllers/methods

I don't know if it's good practice. But I think that I can put this part of code:
$categories = DB::table('categories')
//[something]
->get();
somewhere to not ctrl+c ctrl+v in many places. Can you tell me what can I do with it in Laravel?
full example:
class FirstController extends Controller
{
public function index()
{
$articles = DB::table('articles')
//[something]
->get();
$categories = DB::table('categories')
//[something]
->get();
return view('pages.home', compact('articles', 'categories'));
}
public function show($id)
{
$categories = DB::table('categories')
//[something]
->get();
$article = Article::findOrFail($id);
return view('pages.show', compact('article', 'categories'));
}
}
class SecondController extends Controller
{
public function index()
{
$categories = DB::table('categories')
//[something]
->get();
return view('pages.contact')->with('categories', $categories);
}
}
What you might consider is writing a separate Repository (and Service) for every group of database interactions with method names that accurately describe what is going on and then using Laravels Dependency Injection framework to wire it to your controllers. This is a good resource on how to do that. This also looks really promising. This is the recommended approach if you anticipate that this project will become larger and should remain maintainable (and if your time and resources allow it).
You should make the consideration if what you're currently doing is "good enough" or if it would become unmaintainable in the future and change the implementation to using repositories (and possible services).
After studying your code a bit, a CategoryRepository would look something like this:
use Illuminate\Database\ConnectionInterface;
class CategoryRepository {
protected $connectionInterface;
public function __construct(ConnectionInterface $_connectionInterface) {
$this->connectionInterface = $_connectionInterface;
}
public function all() {
return db::table('categories')
//[something]
->get();
}
}
which you can then reference and use in your controllers like so:
class FirstController extends Controller {
protected $categoryRepository;
public function __construct(CategoryRepository $_categoryRepository) {
$this->categoryRepository = $_categoryRepository;
}
...
public function show($id) {
$categories = $this->categoryRepository->all();
$article = Article::findOrFail($id);
return view('pages.show', compact('article', 'categories'));
}
...
}
You could then try to write an get method, a save method etc. After that, you could write an ArticleRepository and incrementally clean up your controller.
I haven't verified this code so copy-and-paste with caution.
What you need is called View Composer in Laravel.
View composers are callbacks or class methods that are called when a view is rendered. If you have data that you want to be bound to a view each time that view is rendered, a view composer can help you organize that logic into a single location.
More about View Composers: https://laravel.com/docs/5.2/views#view-composers

Set a eager loading function in my eloquent Object

To avoid duplicate code, I would like to create a function eagerLoading() in my eloquent model. Here is my code:
Model Product:
public function scopeActive($query)
{
return $query->where('active', 1);
}
public function eagerLoading($query)
{
return $query->with([
'owners',
'attributes',
'prices' => function ($query)
{
$query->orderBy('created_at', 'desc');
$query->distinct('type');
}
]);
}
MyController:
$products = Product::active()->eagerLoading()->paginate(100);
return $this->response->withPaginator($products, $this->productTransformer);
But when using this, I have this error : Call to undefined method Illuminate\Database\Query\Builder::eagerLoading().
How should I use my function?
Your eagerLoading() method is just another scope, like your scopeActive() method. In order to do what you want, you need to rename it to scopeEagerLoading().
Right now, Product::active() is returning an Eloquent Query Builder. You are then trying to call eagerLoading() on that, and the method doesn't exist. By prefixing the method with scope, it tells the query builder to call the method on the Model for which it is querying.
From the documentation:
"To define a scope, simply prefix an Eloquent model method with scope."
Check documentation at: https://laravel.com/docs/5.1/eloquent#query-scopes
So you need to rename your method to have "scope" at the beginning.
Change public function eagerLoading($query) to be public function scopeEagerLoading($query)

Where do we have to write queries in Laravel: in model, controller or routes?

I'm little confused with the database queries in the laravel, where do we have to write our queries: in controllers, models or routes ?
I've been through many tutorials and I see so much difference. Just creating confusion.
Kindly explain somebody
It depends on different factors, but in short you can write them both in Model, Controllers or Repositories
If you're writing a controller action and you need a query that you'll use only once, it's perfectly fine to write the query directly in the controller (or even in the route's closure ).
For example, if you want to get all users of type admin:
$admins = User::where('type', 'admin')->get();
Now, suppose you need to get the admins in more than one controller method; instead of rewriting the same query, you can create a Repository class to wrap the access to the users' Model and write the query inside the Repository:
class UserRepository
{
public function getAllAdmins()
{
return User::where('type', 'admin')->get();
}
}
Now in your controllers you can inject the Repository and use the same method of the Repository to get the admin users: this will keep your code DRY as you don't have to repeat the same query among the controllers' actions
Controller
public function __construct(UserRepository $userRepo)
{
$this->userRepo = $userRepo;
}
//controller action
public function index()
{
$admins = $this->userRepo->getAllAdmins();
}
Finally, let's suppose you need a query to count the number of the admin users. You could write this query in the UserRepository:
public function getAdminNum()
{
return User::where('type', 'admin')->count();
}
And it would be ok, but we can note that the User::where('type', 'admin') fragment of the query is shared with the query in getAllAdmins So we can improve this by using query scopes :
User Model
public function scopeAdmins($query)
{
return $query->where('type', 'admin');
}
by this, in the UserRepository methods we can rewrite our previous queries as:
public function getAllAdmins()
{
return User::admins()->get();
}
public function getAdminNum()
{
return User::admins()->count();
}
And i've just showed you a case in which a query would be writed inside a Model
You do not write any query in Model. Model is just for mapping the class that you are going to use for a table like User Model will be mapped to users (plural of model name).
You do not write queries in the routes closures like this
Route::get('/', ['as' => 'home', function(){
$totalProblems = Problem::count();
$solvedProblems = Problem::where('solved', 1)->get()->count();
$unsolvedProblems = Problem::where('solved', 0)->get()->count();
return view('Pages.index', ['totalProblems' => $totalProblems, 'solvedProblems' => $solvedProblems, 'unsolvedProblems' => $unsolvedProblems]);
}]);
This is considered as bad practice, its just for testing purposes.
You always write your queries in the controller method associated with your route like this
Route::get('test', 'HomeController#test');
and in your HomeController
<?php namespace App\Http\Controllers;
use App\Problem;
class HomeController extends Controller {
public function test(){
$user = User::all();
return view('Pages.test')->withUser($user); //or
return view('Pages.test')->with('user' , $user);
}
}

Laravel 4 passing database query from model to controller - error call to member function on non-object

Confused about why this isn't working, trying to pass a database query function to my controller. I am receiving the error Call to a member function getCompanyData() on a non-object
Review.php (Model)
class Review extends Eloquent {
public function getCompanyData($company)
{
return $this->select('head', 'body', 'logo', 'name')
->where('company', '=', $company)
->firstOrFail();
}
}
ReviewController.php
class ReviewController extends BaseController {
protected $review;
public function __construct(Review $review)
{
$this->beforeFilter('csrf', array('on' => 'post'));
$this->review = $review;
}
public function show($company)
{
$data = $this->review->getCompanyData($company);
return View::make('reviews.show', compact('data'));
}
}
I'm not sure about the problem but since you mentioned you want be able to call Review::method() but don't want to declare the method as static, so, in this case, it's possible to call using static :: syntax a non-static method declared in an Eloquent Model in Laravel using scope like this:
class Review extends Eloquent {
public function scopeGetCompanyData($query, $company)
{
return $query->select('head', 'body', 'logo', 'name')
->where('company', '=', $company);
}
}
Now you can call the getCompanyData method from your controller like this way:
$data = Review::getCompanyData($company)->firstOrFail();
So review is not an object, and you are trying to call its method like it is object. It is probably array. I see you provided Request $request reference and you expect it to be and object. It sometimes happens to me while passing values to view. Try to track type of review.
Update:
Some other things to consider are: Why did you pass Review through constructor, when it is model that extends Eloquent and it should be visible ? Does Review really extends Eloquent ?

Using controller in view with Laravel

I have simple function in one of my controller (members):
function action_data($array) {
$datamembre = DB::table('members')->where('id', '=', $id)->first();
return $datamembre;
}
I want use it in the view of another controller, I do this in my template:
$datamembers = Controller::call('members#data', array($members_id));
Is there any better or proper way to do it?
The best would be to put it into a Member model IMO.
Use view composer http://laravel.com/docs/views#view-composers
View::composer(array('home', 'profile'), function($view)
{
//
});
update
You can put the method in BaseController, all controllers extend it, so you could get this method in any controller/view. And make it static.
// in BaseController.php (L4) or Base.php (L3)
static public function action_data($array) {
$datamembre = DB::table('members')->where('id', '=', $id)->first();
return $datamembre;
}
In the view
BaseController::action_data($array); //L4
Base_Cotroller::action_data($array); //L3
Hope it works. Haven't tested it.

Categories