In my laravel 5.5 api I have a lot of response message like
"You successfully completed some action..".
At the moment I have stored them as constants in the controller they
are used. I want to move all of them to a single location, so if I need to change them later I don't have to hunt for them in each controller.
What is the best approach for this usecase?
What about Laravel localization? Then using it as trans('success-message-key-here')
In your use case, I would make static functions to call the responses the same way.
class ResponseMessage
{
public static function succesfulResponse()
{
return response('successfull', 200);
}
public static function failedResponse()
{
return response('fail', 400);
}
}
Use case:
...
return ResponseMessage::succesfulResponse();
Another way is to take the parent controller, which is often just named Controller in your controller folder, which you extend from.
class controller
{
public function succesfulResponse()
{
return response('successfull', 200);
}
}
Now you are not in a static context, but you can use the functions if you extend from it.
class yourController extends Controller
{
public function get($id) {
...
return $this->succesfulResponse();
}
}
You could make use of the translations files even if you are just supporting one language.
In your controller you would have something like:
$message = \Lang::get('directory/file.str1');
And your translation file:
return [
'str1' => 'You successfully completed some action.',
];
In resource/lang/en directory (in other words Localization you can put your message like this
ApiMessage.php
return [
'success' => 'success message',
];
Then in your controller you can call like this
public function somefunction(Request $request)
{
// your logic
return response()->json(__('apiMessages.success'));
}
here en folder denotes your local language (default is english symbolized as en)
Related
How do I pass a true false value to the controller from the redirect in the class and to the router and back to another function in the same controller class if that makes sense
Like
public function 1() {
return redirect('route2');
}
public function2() {
I need to access the variable here that some how gets passed from the first function
}
Because these functions are both on my main controller and I need to pass a variable through the route
and back into the controller or is there a way to put a state variable on the class or something I just need to call a function on the controller with conditions from the previous controller function that called called the redirect route.
Also sorry if I am mixing up class and function I am new to laravel and MVC in general.
You can do something like this:
public function first() {
return redirect()->action(
[YourController::class, 'second'], ['value' => true]
);
}
public function second($value = null) {
// whatever you want
}
https://laravel.com/docs/9.x/redirects#redirecting-controller-actions
I think this code help you:
public function 1() {
return to_route('YOUR_ROUTE_NAME', ['value' => 'some things...']);
}
public function2(Request $request, $value) {
// Use the value passed as a route parameter
// $value is 'some things...'
}
Tried looking for the answer to this everywhere but having no luck so far...
Basically I want my web route to use a slug for its URL, but I want to use ID for the API route. So...
http://myurl.com/chapter/my-chapter-slug
and
http://myurl.com/api/chapter/1234
Have tried various combinations of things in the getRouteKeyName method (if(Request::route()->named('myapiroute'), if(Request::isJson() etc...) but I think these might be being checked against the page it's running on, rather than the route I'm trying to generate?
I'm thinking maybe I need to extend the base model to have a separate one to use with my API maybe?
So I'd have...
class Chapter extends Model
{
public function getRouteKeyName()
{
return 'slug';
}
....
}
and then...
class ApiChapter extends Chapter
{
public function getRouteKeyName()
{
return 'id';
}
....
}
But not sure how I'd structure this in the most "Laravel" way? Or is there a better/tidier solution?
define your route for example like
Route::get('chapters/{chapter}','ChapterController#show'); // find by slug
Route::get('api/chapters/{chapter}','ApiChapterController#show'); // find by id
for web controller
class ChapterController extends Controller
{
public function show(Request $request,$slug)
{
$instance = Model::whereSlug($slug)->first();
}
}
for api
class ApiChapterController extends Controller
{
public function show(Request $request,$id)
{
$instance = Model::find($id);
}
}
You can define 2 different routes for that but unfortunatelly you will not be able to use model binding and you will have to look for the model like:
public function show(Request $request,$slug) {
$instance = Model::whereSlug($slug)->first();
}
as shown below: https://stackoverflow.com/a/48115385/6525417
In my web.php file, I have a route that looks like this:
Route::get('/', 'HomeController#getFeed');
And in my api.php file, I have a route that looks like this:
Route::get('feeds', 'HomeController#getFeed');
Notice that they both call the same method, getFeed().
Is there a way to distinguish whether the call came from the web route vs the API route in the controller's method? I need to be able to return two different responses, one for the web route and one for the API route.
Here is the HomeController.php class:
class HomeController extends Controller
{
public function getFeed() {
$user = Auth::user();
// How to check if call is from web route or API route?
// Need to return two different responses for each scenario.
}
}
Thanks.
All routes from api.php are automatically prefixed with 'api/'
So you can use he below code to check
if (Request::is('api*')) {
echo "request from api route";
exit();
}else{
echo "request from web";
exit();
}
I use \Request::is('api/*')
if(\Request::is('api/*'))
return 'API';
else
return 'Non-API';
Alternatively you can check using the route name;
if(\Request::route()->getName() == 'APIFeed')
return 'API';
else
return 'Non-API';
Make sure to set the route name;
In web.php
Route::get('feeds', 'HomeController#getFeed')->name('WebFeed');
In api.php
Route::get('feeds', 'HomeController#getFeed')->name('APIFeed');
replace this line
Route::get('feeds', 'HomeController#getFeed');
with
Route::get('api/feeds', 'HomeController#getFeed');
means add api prefix in all of your api routes.
it will help you to identify which route come from api and which not.
to check you can use below code
if (Request::is('api*')) {
echo "request from api route";
exit();
}else{
echo "request from web";
exit();
}
You can use
$currentRoute = Illuminate\Routing\Router::getCurrentRoute(); // Returns a Route
$currentRoute->uri(); // returns the uri of the cureent route
https://laravel.com/api/5.4/Illuminate/Routing/Router.html#method_getCurrentRoute
https://laravel.com/api/5.4/Illuminate/Routing/Route.html
Hope this helps. :)
In your shoes, I would have created 3 controllers to handle the requests and like Niraj proposed, separate routes by prefix the api route with /api/
class HomeController extends Controller
{
public function getFeed(entrypoint) {
$user = Auth::user();
// do the common magic here ...
}
}
class WebHomeController extends HomeController
{
public function getFeed() {
feed = this.getFeed();
// do the crazy web magic here ...
}
}
class APIHomeController extends HomeController
{
public function getFeed() {
feed = this.getFeed();
// do the crazy api magic here ...
}
}
Route::get('feeds', 'WebHomeController#getFeed');
Route::get('api/feeds', 'APIHomeController#getFeed');
Here's how you access parent methods from child controller
class WebHomeController extends HomeController
{
//get parent methods and protected variables
public function __construct()
{
parent::__construct();
}
public function getFeed() {
//access parent method
$p = $this->getFeed();
feed = this.getFeed();
// do the crazy web magic here ...
}
}
I have to build an api.
It has one route. The client is sending a POST request with an XML.
Based on that xml, I have to decide witch controller#action to be called.
And I have a lot of controllers.
Unfortunately I can't modify the client side.
Do you have any suggestion how can i do that in a Laravel way?
For example
POST["body"] =
"...
<controller>content</controller>
<action>index</action>
..."
I want to call a ContentController::index()
Thx!
Thx for the reflection stuff. It is a big magic, worth the effort to look into it deeper.
I have no problem to parse the xml. So here is a simplier example
URL: /api/request/content/show
Routes.php
Route::get('api/request/{controller}/{action}', 'ApiController#request');
ApiController.php
class ApiController extends Controller
{
public function request($controller, $action)
{
//some error check
$controller = 'App\Http\Controllers\\' . ucfirst($controller) . 'Controller';
$params = "Put some params here";
$reflectionMethod = new \ReflectionMethod($controller, $action);
$reflectionMethod->invoke(new $controller, $params);
}
}
ContentController.php
class ContentController extends Controller
{
public function show($params)
{
dd($params);
}
}
And it is working!
Thx a lot!
A better option is to use App::call(); invoking controller with ReflectionMethod might not let you use response() inside your new forwarded controller and other laravel goodies.
Here is my try on this: /api/request/content/show
Routes web.php or api.php
use App\Http\Controllers\ApiController;
Route::get('api/request/{controller}/{action}', [ApiController::class, 'request']);
ApiController.php
class ApiController extends Controller
{
public function request($controller, $action)
{
//some error check
return App::call('App\Http\Controllers\\'.ucfirst($controller).'Controller#'.$action);
}
}
ContentController.php
use Illuminate\Http\Request;
class ContentController extends Controller
{
public function show(Request $request)
{
dd($request);
}
}
This will allow you more freedom.
Is it a bug or a feature?
I have two controllers IndexController and TestController.
The first one looks like this:
class IndexController extends \Phalcon\Mvc\Controller
{
public function indexAction()
{
$products = $this->basket->get('products', []);
$products[] = uniqid('index.index');
$this->basket->set('products', $products);
}
public function testAction()
{
var_dump($this->basket->products);
}
}
I just save an array in a session with indexAction and show that data in testAction.
For the first request output for index/test is an empty array. But the second and all following requests add one new element. If I comment line $this->basket->set('products', $products); then the next request to index/test will add another value to array but after that extra pushing to array does not happen.
Then I add
class TestController extends \Phalcon\Mvc\Controller
{
public function indexAction()
{
$products = $this->basket->get('products', []);
$products[] = uniqid('test.index');
$this->basket->set('products', $products);
die();
}
public function testAction()
{
var_dump($this->basket->products);
die();
}
}
But for request test/test I again get changing in session variable.
Looks like that route index/index always executes before any other routes. Is it a feature, bug or some sort of misconfiguration? I use standard configuration for multimodule application from official documentation.
This is more than likely because your browser is hitting /favicon.ico in the background. I've been stung by this a number of times across different frameworks.
Try putting a favicon.ico file (or a rule to block that path) and see if the problem persists.