im learning about laravel and im following some videos from laracasts, but im having a issue in displaying the data from the controller, i made all right, but still appears me empty array, the instance Card isnt working, here is my code:
Model:
Card.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Card extends Model
{
//
}
route:
Route::get('cards/{card}', 'CardsController#show');
CardsController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Card;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class CardsController extends Controller
{
public function show(Card $card)
{
return $card;
//$card = Card::find($card);
//return view('cards.show', compact('card'));
}
}
What you are attempting is called "Route Model Binding" and it seems to me that you are using Laravel 5.1 or lower (where route model binding is not implicit).
If you are using Laravel 5.2 or higher that code should just work. https://laravel.com/docs/5.3/routing#route-model-binding
But, if you are in Laravel 5.1 you need to do an additional step: https://laravel.com/docs/5.1/routing#route-model-binding
In the provider class RouteServiceProvider, in the boot method, you need to bind which route name {card} should bind to which Model, in this case Card.
So, you do something like this:
public function boot(Router $router)
{
parent::boot($router);
$router->model('card', \App\Card::class);
}
If you add that, the router will know that when it finds {card} it should get that number and do the Card::findOrFail with the ID automatically and if the model is found it will be passed down to your controller.
First of all, you will need to add the fillable protected property to your Eloquent model! Now, on to the good part.
In your routes file you have
Route::get('cards/{card}', 'CardsController#show');
This code, in a nutshell, will pass the card ID to your show function in your CardsController class. Eg. for this route: https://example.com/cards/5, it will in essence call the function show like this: show(5). In your code, you have that the show parameter is typehinted to be a Card. This is wrong. This is going to be an integer.
Thus, what you really need to do is check whether this ID exists and then pass the relevant information to your view. Something like this:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Card;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class CardsController extends Controller
{
/**
* Show the relevant card information
*
* #param $card This is the card ID (its an integer)
*/
public function show($card)
{
$card = Card::findOrFail($card);
return view('cards.show')->with(compact('card'));
}
}
Related
I am working on a Laravel control panel project where we should be able to toggle from one site to another and get the detail of the site based on the ID passed in the route.
In itself this is quiet easy to do but as I will have several controllers using this technique it means for each controller and each controller instance I will have collect the site instance and it does not look very user friendly due to the many repetitions.
Here is what I have:
Route:
Route::get(
'cp/site/{website}/modules/feeds',
'App\Http\Controllers\Modules_sites\Feeds\FeedController#index'
)->name('module_site.feeds.index');
Model:
class Website extends Model
{
use HasFactory;
protected $primaryKey ='site_id';
}
The database is simple with an id (site_id) and name
Controller:
public function index(Website $website)
{
dd($website -> name);
}
The above is working fine but I am going to end with dozens of methods across multiple controllers doing the same thing, and what if changes are required.
I have looked at the ID of using the AppServiceProvider to create the Website instance and then pass it to the controllers and views but I can't do this as the route is not defined at this stage and I only seem to be able to pass this to the view.
Essentially, I am looking to create something similar to the auth()->user() method that is available from controllers and routes without the needs to pass it to each controller.
Is this possible?
Perhaps you could use middleware to set this value? Something like this to put it in the session globally:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckWebsite
{
public function handle(Request $request, Closure $next): mixed
{
$request->session()->put("website", $request->route("website"));
return $next($request);
}
}
Or this on a per-controller basis:
<?php
namespace App\Http\Controllers\Modules_sites\Feeds;
use App\Http\Controllers\Controller;
use Closure;
use Illuminate\Http\Request;
class FeedController extends Controller
{
public function __construct()
{
$this->middleware(function (Request $request, Closure $next) {
$this->website = $request->route("website");
return $next($request);
});
}
public function index()
{
dd($this->website->name);
}
}
Also worth mentioning that routes are not defined like that in Laravel 8 any longer. It should look like this:
Route::get(
'cp/site/{website}/modules/feeds',
[FeedController::class, 'index']
)->name('module_site.feeds.index');
With an appropriate import for the controller class.
as you primary key is not id so it will not work automatically you need to tell laravel to search by column name
code will be
Route::get('cp/site/{website:site_id}/modules/feeds', 'App\Http\Controllers\Modules_sites\Feeds\FeedController#index')->name('module_site.feeds.index');
you need to use {website:site_id}
ref link https://laravel.com/docs/8.x/routing#customizing-the-default-key-name
i´m studying laravel but having some doubts..
Controller
namespace App\Http\Controllers;
use App\ItemNfe;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class ItensNfeController extends Controller
{
public function edit($id,ItemNfe $itemNfe)
{
//i don´t want to have to make this select below
//$itemNfe = DB::table('itens_nfe')->where('id_itemnfe',$id)->get();
// dd($itemNfe); this dd() returns model attributes on few of my controllers only
return view...
}...
Model: (note i´m not using laravel convention but it´s informed)
namespace App;
use Illuminate\Database\Eloquent\Model;
class ItemNfe extends Model
{
protected $table = 'itens_nfe';
protected $primaryKey = 'id_itemnfe';
protected $fillable = [
'id_itemnfe','fk_venda', 'fk_produto'...
];
public function nfe()
{
return $this->belongsTo('App\Nfe'); //this is one diference among others models, but apparently doesn´t affects when i tested without this code.
}
}
The route i´m using is the same for everyone.. "resource routes"
At the first 2, i have the attributes returning, but not at the last one...
Route::resource('/usuarios', 'UsuariosController');
Route::resource('/nfes', 'NfesController');
Route::resource('/itensnfe', 'ItensNfeController');
The Url used is:
https://localhost/erpoverweb/public/itensnfe/1/edit
If needing more code please tell me... thanks!
If you don't want to manually search the database for the entry, you can use Laravel Container do perform a Dependency Injection. https://laravel.com/docs/7.x/container#introduction
public function edit(ItemNfe $itemNfe)
{
// Returns the model, and you didn't need to manually searched.
// Laravel automaticly injects this for you.
dd($itemNfe);
}
Sounds like you are looking for Route Model Binding (implicit at that). This requires that the route parameter name and the name of the parameter of the method signature for that route match.
public function edit(ItemNfe $itensnfe)
The resource route with resource name 'itensnfe' should make the parameter 'itensnfe'.
If you don't make these match you will just end up with Dependency Injection which would inject a new model instance.
Laravel 7.x Docs - Routing - Route Model Binding - Implicit Binding
I am trying laravel sanctum for the first time.
I want to issue tokens for an Eloquent Model called Campaign.
This is my Campaign.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Laravel\Sanctum\HasApiTokens;
class Campaign extends Model
{
use HasApiTokens;
protected $guarded = ['id'];
public function users()
{
return $this->belongsToMany(User::class)->withPivot(['percentage'])->withTimestamps();
}
}
As you can see, I put the HasApiTokens trait on it.
With this, I can issue a token to any campaign like that:
$campaign->createToken('my-token-name');
So far, so good. It works and is correctly stored at the database.
The problem begins when I try to use the token to make any request protected with sanctum's middleware. This is the error that shows when I do it:
Call to undefined method App\\Campaign::getAuthIdentifier()
Well, I guess this getAuthIdentifier() comes from use Illuminate\Foundation\Auth\User class, which is commonly imported on the User model as Authenticatable;
I tried to create this method on my Campaign model and give it a try, that's what I've done:
public function getAuthIdentifier()
{
return 'id';
}
When I tried to post again, it seems to work. But I think it's not correct because it's kind weird. And it gets even worse when I call auth()->user() and I am able to access the Campaign object. I know that this is a consequence of what I have done here.
Can this package issue tokens based on something that is not actually an User?
If you know how to do it correctly, I would appreciate an answer :)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Auth\Authenticatable;
class Campaign extends Model implements AuthenticatableContract
{
use HasApiTokens,Authenticatable;
protected $guarded = ['id'];
public function users()
{
return $this->belongsToMany(User::class)->withPivot(['percentage'])->withTimestamps();
}
}
In addition to your comment, if you like to get campaign send token in the header in the request and then search in the token table to find the related campaign
I'm using Laravel and trying to do an SQL query from my Controller in a public function, but I'm really confused where I would put my table in the argument and if quotes go around the argument. Here is my code
public function selectMethod(){
$results = DB::select('select firstname from people where id = 1');
print_r($results);
return view('pages.selectMethod');
}
table is called people
My .env is configured to my database correctly and I get this error
FatalErrorException in AboutController.php line 90:
Class 'App\Http\Controllers\DB' not found
Thanks !
you should add use Illuminate\Support\Facades\DB;
at the top of your page
for example :
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show a list of all of the application's users.
*
* #return Response
*/
public function index()
{
$users = DB::table('users')->get();
return view('user.index', ['users' => $users]);
}
}
Your error clearly states: Class 'App\Http\Controllers\DB' not found
Hence just use DB in your class. Add:
use DB;
At the top of the file just below the namespace line.
Also, I would suggest you to use Eloquent for your queries. It will make your life a lot easier and your code a lot beautiful.
I am new to Laravel 5 coming from CodeIgniter background. I have habit to not play with routes.php. CodeIgniter automatically maps methods like controllerName/MethodName. But in Laravel 5 I am trying to do same by registering a controlller by writing this at top of app/http/sroutes.php:
Route::controllers([
'admin/user' => 'Admin\AdminUserController',
]);
When I run php artisan route:list it show that controller is registered. But when I see URL /public/admin/user/addRole it show addRole method not exist while I have created a method in AdminUserController.
Admin/AdminUserController.php
<?php namespace App\Http\Controllers\Admin;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class AdminUserController extends Controller {
public function getaddRole(){
echo "adding Roles";
}
}
Routes.php
Route::controllers([
'admin/user' => 'Admin\AdminUserController',
]);
<?php namespace App\Http\Controllers\Admin;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class AdminUserController extends Controller {
public function getAddRole(){
echo "adding Roles";
}
}
NB: Notice getAddRole() not getaddRole(), use camelCase
If your controller action contains multiple words, you may access the action using "dash" syntax in the URI like this:
public/admin/user/add-role
It's hard to tell because I don't see your controller code but I assume you missed adding a HTTP verb to the method name. Like:
public function getAddRole(){
// ...
}
If you want the method to match any request method, use any:
public function anyAddRole(){
// ...
}