Call function in Controller using URL - php

Im comming from CodeIgniter.
There if you had a controller like this:
class Article extends CI_Controller{
public function comments()
{
echo 'Look at this!';
}
}
You could access the comments() function using the URL like this: example.com/Article/comments
How could I do something similar in Laravel?
The way I do it right now is specifiying a route like this:
Route::get('/Article/comments}', 'ArticleController#comments');
But I was hoping for a more dynamic way to do it as I don't want to keep on creating new routes for every function

The recommended way of dynamically calling controllers methods via URL, for Laravel users, is via RESTful Controllers:
<?php
class ArticleController extends controller {
public function getComment()
{
return 'This is only accesible via GET method';
}
public function postComment()
{
return 'This is only accesible via POST method';
}
}
And create your route using telling Laravel this is a RESTful Controller:
Route::controller('articles', 'ArticlesController');
Then if you follow
http://laravel.dev/articles/comments
Using your browser, you should receive:
This is only accesible via GET method
The way you name your controllers methods (getComment, postComment, deleteComment...) tells Laravel wich HTTP method should be used to call those methods.
Check the docs: http://laravel.com/docs/controllers#restful-controllers
But you can also make it dynamic using PHP:
class ArticlesController extends Controller {
public function comments()
{
return 'Look at this!';
}
public function execute($method)
{
return $this->{$method}();
}
}
Use a controller like this one:
Route::get('Article/{method}', 'ArticleController#execute');
Then you just have to
http://laravel.dev/Article/comments

I'll recommend that you stick with the laravel's way to create REST controllers, because that way you can have control over what HTTP Verb is being called with the controller method. The laravel way of doing this is just to add the HTTP Verb in front of the controller method, for your method comments if you want to specify a GET request in Laravel the name of the method would look like getComments.
For example, if you need to do a GET request for the article/comments URI, and then to create a new comment you want to use the same URI with another HTTP verb, lets say POST, you just need to do something like this:
class ArticleController extends BaseController{
// GET: article/comments
public function getComments()
{
echo 'Look at this!';
}
// POST: article/comments
public function postComments()
{
// Do Something
}
}
Further reading:
http://laravel.com/docs/controllers#restful-controllers
Now for your specific answer, this is the Laravel way of doing what you requested:
class ArticleController extends BaseController{
public function getComments()
{
echo 'Look at this!';
}
}
and in the routes.php file you'll need to add the controller as follows:
Route::controller('articles', 'ArticleController');

Related

Laravel using separate controller for separate logic

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.

Add a route to handle multiple HTTP requests in Slim PHP

I am using the following code for "Routing using methods inside classes:"
$app->any('/contacts', 'Contacts:home');
My class looks like:
class Contacts {
public function home() {
return 'something';
}
}
The above code works fine for me and when I open "http://localhost:3000/contacts"
The Problem is when I try to handle multuple HTTP request
$app->group('/users/{id:[0-9]+}', function() {
$this->map(['GET', 'POST'], '', 'Users');
});
Is there anyway, I can pass class name such as Users in the above pseudo code and the code works for me, The class would be something like:
class Users {
function get() {
return 'asd';
}
function post() {
return 'post';
}
}
In such a way, that my request listens to the appropriate method.
You would need to create a method that sorts out the current route's details than calls the correct method.
You can determine which method was used by calling the $request->getOriginalMethod(); function, then using call_user_func_array(); function you can call whichever of your functions is appropriate for the current method.

How to call controller function without declared in Route in Laravel 5.1?

i want to call the controller => function without specifying in route in Laravel 5.1.
such as controller / function
Example: admin/delete
so i want to call the above controller's function without specifying in routes is their any way to do that?
Also, if it is possible then how to pass parameters to that function?
I think you are looking for RESTful Controllers.
So in your route file you only have:
Route::controller('admin', 'AdminController');
and in your controller:
class AdminController extends BaseController {
public function show($adminId)
{
//
}
public function destroy($adminId)
{
//
}
}

How to resolve BadMethodCallExeption in Laravel (IoC Container)

When I add Route::resource('api', 'ApiController'); to my app/Http/routes.php, I get this error:
BadMethodCallException Method [index] does not exist.
My api controller looks like this:
<?php
class ApiController extends BaseController
{
public function getIndex()
{
echo "No Access";
}
public function postIndex()
{
// content here ...
}
public function check_ban($user, $gameBit, $ip)
{
// content here ...
}
public function check_balance($userid, $gameid, $serverid)
{
// content here ...
}
public function purchase_item($xml)
{
// content here ...
}
public function LoginRequest($xml)
{
// content here ...
}
public function CurrencyRequest($xml)
{
// content here ...
}
public function ItemPurchaseRequest($xml)
{
// content here ...
}
}
My api should handle out game login request, buying items, ban check and so on, but I get the error described above.
How do I resolve it please?
When you are using following to declare a resourceful route
Route::resource('api', 'ApiController');
Then let Laravel generate methods for you so go to command prompt/terminal and run:
php artisan controller:make ApiController
This will create a ApiController resourceful controller in app/controllers directory and all the methods will be (Method's skeleton) created. To make sure which method listens to which URI and HTTP method, run php artisan routes from command prompt/terminal so you'll get the idea. Read more about resourceful controllers on Laravel website.
If you want to declare your own methods against HTTP verbs then create a RESTful controller and to create a RESTful controller you don't have to run any artisan command from terminal but declare the route using:
Route::controller('api', 'ApiController');
Then create methods prefixing with HTTP verbs for responding to that verb for example:
class ApiController extends BaseController {
// URL: domain.com/api using GET HTTP method
public function getIndex()
{
//...
}
// URL: domain.com/api/profile using POST HTTP method
public function postProfile()
{
//...
}
// ...
}
If you run php artisan routes then you will be able to see all the URIs and method mapping. Check RESTful controllers on Laravel website.

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