Automatically Load/Show Laravel View File - laravel

I am thinking of any techniques of autoloading the view files according to url.
For example:
public function addProducts()
{
return view('admin.addProducts');
}
public function editProducts()
{
return view('admin.editProducts');
}
public function allProducts()
{
return view('admin.allProducts');
}
Here, the Controller's method name is identical to view file name. So, I am thinking, if it is possible to load the view files without writing same kind of method again and again.
Enlighten me.

If your route only needs to return a view, you may use the Route::view method.
For example:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
read more here

It's the call PHP magic, man. https://repl.it/#Piterden/PHP-call-magic?language=php
public function __call($method, $parameters)
{
if (str_contains($method, 'Product')) {
return view("admin.{$method}");
}
}
btw, it's not a good practice for controller.

Related

Route not defined when passing parameter to a route

I have a named route with a parameter which looks like this...
Route::get('/profile/{user_id}', [ProfileController::class, 'profile'])->name('profile');
Now in one of my controller,
I have a function that calls this route like this
public function _myFunction($some_data) {
return redirect()->route('profile', [$some_data->user_id]);
}
and in my ProfileController's profile() function, I have this.
public function profile() {
return view('modules.profile.profile');
}
I've followed the documentation and some guides I found in SO, but I got the same error,
"Route [profile] not defined."
can somebody enlighten me on where I went wrong?
Here's what my routes/web.php looks like...
Route::middleware(['auth:web'])->group(function ($router) {
Route::get('/profile/{user_id}', [ProfileController::class, 'profile'])->name('profile');
});
When calling the route, you should pass the name of the attribute along with the value (as key vaue pairs). In this case, your route is expecting user_id so your route generation should look like this:
return redirect()->route('profile', ['user_id' => $some_data->user_id]);
Read more on Generating URLs To Named Routes in Laravel.
I solved the issue, and its really my bad for not providing a more specific case information and made you guys confused.
I was using socialite and called _myFunction() inside the third party's callback..
After all, the problem was the socialite's google callback, instead of placing the return redirect()->route('profile', [$user->id]) inside _myFunction(), what I did was transfer it to the callback function.
So it looked like this now...
private $to_pass_user_id;
public function handleGoogleCallback()
{
try {
$user = Socialite::driver('google')->user();
$this->_myFunction($user);
return redirect()->route('profile', [$this->to_pass_user_id]);
} catch (Exception $e) {
dd($e->getMessage());
}
}
public function _myFunction($some_data) {
... my logic here
$this->to_pass_user_id = $some_value_from_the_logic
}

Returning same variable to every controller in laravel

I need to send the same result to almost every view page, so I need to bind the variables and return with every controller.
My sample code
public function index()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.index', compact('drcategory','locations'));
}
public function contact()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.contact', compact('drcategory','locations'));
}
But as you see, I need to write same code over and over again. How can I write it once and include it any function whenever I need?
I thought about using a constructor, but I cannot figure out how I can implement this.
You are able to achieve this by using the View::share() function within the AppServicerProvider:
App\Providers\AppServiceProvider.php:
public function __construct()
{
use View::Share('variableName', $variableValue );
}
Then, within your controller, you call your view as normal:
public function myTestAction()
{
return view('view.name.here');
}
Now you can call your variable within the view:
<p>{{ variableName }}</p>
You can read more in the docs.
There are a few ways to implement this.
You can go with a service, a provider or, like you said, within the constructor.
I am guessing you will share this between more parts of your code, not just this controller and for such, I would do a service with static calls if the code is that short and focused.
If you are absolutely sure it is only a special case for this controller then you can do:
class YourController
{
protected $drcategory;
public function __construct()
{
$this->drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
}
// Your other functions here
}
In the end, I would still put your query under a Service or Provider and pass that to the controller instead of having it directly there. Maybe something extra to explore? :)
For this, you can use View Composer Binding feature of laravel
add this is in boot function of AppServiceProvider
View::composer('*', function ($view) {
$view->with('drcategory', DoctorCategory::orderBy('speciality', 'asc')->get());
$view->with('locations', Location::get());
}); //please import class...
when you visit on every page you can access drcategory and location object every time
and no need to send drcategory and location form every controller to view.
Edit your controller method
public function index()
{
return view('visitor.index');
}
#Sunil mentioned way View Composer Binding is the best way to achieve this.

Laravel policies - passing the class as a variable to $user->can() method doesn't work

I have a route with dynamic model recognition. In other words, I take the desired model as an argument and use it in the controller. I have complex authorization in my app and I need to pass the model class name as a variable to the $user->can() method for using policies, but for some reason it doesn't work. Here's my code:
Policy:
public function view($user, Model $model) {
return $user->model_id == $model_id;
}
public function create($user) {
return $user->isAdmin();
}
Controller:
public function createModel($model) {
$model_class = $model . '::class';
if (Auth::user()->can('create', $model_class)) {
return $model_class::create();
}
return 'invalid_permissions';
}
If I hardcode the model class name it works. For example, if my model is 'Car' and in the controller I put:
if (Auth::user()->can('create', Car::class)) {
Anybody got any ideas why this is so and how to fix it? I hope that it's possible because I would have to change my whole concept if it isn't.
*Note: this is example code, not my actuall classes

The return of view() in Laravel?

I am just learning Laravel 5.1 framework, I find a puzzling problem.
First, I create a model named 'Page', then I create a controller named 'HomeController', the method code is following:
public function index()
{
return view('home')->withPages(Page::all());
}
I cannot find 'withPages()' function, so I find helper function view() return \Illuminate\View\View, so I find 'vendor/laravel/framework/src/Illuminate/View/View.php', there is a "__call()", so I get it.
But I try to delete this function, my site is still normal.
did I find the wrong place? I am very puzzled.
... there is a "__call()", so I get it. But I try to delete this function, my site is still normal. did I find the wrong place? I am very puzzled.
Probably.
Laravel 'compiles' all it's core classes into a single file as a performance optimisation.
Try running php artisan clear-compiled and your site should start failing.
This is how I would do it -
public function index()
{
return view()->with('pages', Page::all());
}
If you want to use withPages method, you need to have a variable $pages set in the method.
So your method would look like:
public function index()
{
pages = Page::all();
return view('home')->withPages($pages);
}
Other two options:
public function index()
{
return view('home')->with('pages', Page::all());
}
or
public function index()
{
pages = Page::all();
return view('home')->with(compact('pages));
}
You can use any of these methods.

Codeigniter : calling a method of one controller from other

I have two controllers a and b.
I would like to call a method of controller a from a method of controller b.
Could anyone help explain how I can achieve this?
This is not supported behavior of the MVC System. If you want to execute an action of another controller you just redirect the user to the page you want (i.e. the controller function that consumes the url).
If you want common functionality, you should build a library to be used in the two different controllers.
I can only assume you want to build up your site a bit modular. (I.e. re-use the output of one controller method in other controller methods.) There's some plugins / extensions for CI that help you build like that. However, the simplest way is to use a library to build up common "controls" (i.e. load the model, render the view into a string). Then you can return that string and pass it along to the other controller's view.
You can load into a string by adding true at the end of the view call:
$string_view = $this->load->view('someview', array('data'=>'stuff'), true);
test.php Controller File :
Class Test {
function demo() {
echo "Hello";
}
}
test1.php Controller File :
Class Test1 {
function demo2() {
require('test.php');
$test = new Test();
$test->demo();
}
}
Very simple way in codeigniter to call a method of one controller to other controller
1. Controller A
class A extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_a()
{
}
}
2. Controller B
class B extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_b()
{
require_once(APPPATH.'controllers/a.php'); //include controller
$aObj = new a(); //create object
$aObj->custom_a(); //call function
}
}
I agree that the way to do is to redirect to the new controller in usual cases.
I came across a use case where I needed to display the same page to 2 different kind of users (backend user previewing the page of a frontend user) so in my opinion what I needed was genuinely to call the frontend controller from the backend controller.
I solved the problem by making the frontend method static and wrapping it in another method.
Hope it helps!
//==========
// Frontend
//==========
function profile()
{
//Access check
//Get profile id
$id = get_user_id();
return self::_profile($id);
}
static function _profile($id)
{
$CI = &get_instance();
//Prepare page
//Load view
}
//==========
// Backend
//==========
function preview_profile($id)
{
$this->load->file('controllers/frontend.php', false);
Frontend::_profile($id);
}
I posted a somewhat similar question a while back, but regarding a model on CI.
Returning two separate query results within a model function
Although your question is not exactly the same, I believe the solution follows the same principle: if you're proposing to do what you mention in your question, there may be something wrong in the way you're coding and some refactoring could be in order.
The take home message is that what you're asking is not the way to go when working with MVC.
The best practice is to either use a Model to place reusable functions and call them in a controller that outputs the data through a view -- or even better use helpers or libraries (for functions that may be needed repeatedly).
You can do like
$result= file_get_contents(site_url('[ADDRESS TO CONTROLLER FUNCTION]'));
Replace [ADDRESS TO CONTROLLER FUNCTION] by the way we use in site_url();
You need to echo output in controller function instead of return.
You can use the redirect() function.
Like this
class ControllerA extends CI_Controller{
public function MethodA(){
redirect("ControllerB/MethodB");
}
}
Controller to be extended
require_once(PHYSICAL_BASE_URL . 'system/application/controllers/abc.php');
$report= new onlineAssessmentReport();
echo ($report->detailView());
You can use the redirect URL to controller:
Class Ctrlr1 extends CI_Controller{
public void my_fct1(){
redirect('Ctrlr2 /my_fct2', 'refresh');
}
}
Class Ctrlr2 extends CI_Controller{
public void my_fct2(){
$this->load->view('view1');
}
}
very simple
in first controllr call
$this->load->model('MyController');
$this->MyController->test();
place file MyController.php to /model patch
MyController.php should be contain
class MyController extends CI_Model {
function __construct() {
parent::__construct();
}
function test()
{
echo 'OK';
}
}

Resources