on multiple auth in laravel laravel 8 - laravel

I have this code in the user model class
using this code showing error
Showing like this
model class code
protected function type(): Attribute
{
return new Attribute(
get: fn ($value) => ["user", "admin", "manager"][$value],
);
}

As #Marwelln mentioned you would need PHP8 and you are are using php7.4. (See picture from the link you posted)
You can do Attribute:get(fn($value) =>....) instead

Related

Feature Test in Laravel 8 uses withHeader to set Host invalid?

Since my project has deployed multiple domain names, the API interface that needs to be tested is using the api.example.test domain name as the entrance.
Using $this->get('/v1/ping') in Feature Test will request to www.example.test, I hope to set up $this->withHeader('Host', config('domain.api_domain')) uniformly in setUp in ApiFeatureBaseTestCase to automatically request API related tests to api.example.test Go in.
However, in practice, I found that this is invalid. By tracing the code, I found two codes that may cause the invalid Host setting:
First place (Laravel):
Code in Laravel Framework src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:503, pass the parameter $uri ='/v1/ping' into $this->prepareUrlForRequest($uri) and get a complete Url with the default Host, the return value is http://www.example.test/v1/ping.
Second place (Symfony):
In the code of Symfony HttpFoundation Component Request.php:355, the parsing in $uri will be used first The coming out host is overwritten in the Header as the default Host.
The above two codes eventually caused the Host I set by withHeader to fail. Obviously, in this code logic, Symfony HttpFoundation Component's choice of Host in conflict cannot be considered wrong, but I submitted this question issue was closed when it was given to Laravel Framework.
I don't know if this issue is a bug or feature?
Finally, I am sorry that my question has interrupted everyone's time, but if there is a conclusion on this question, please tell me what should be more appropriate?
My current approach is $this->get($this->api_base_url . '/v1/ping'), but I don’t think this is elegant
3Q!!1
Code example
// File: config/domain.php
return [
'api_domain' => 'api.example.test',
'web_domain' => 'www.example.test',
];
// File: routes/demo.php
Route::domain(config('domain.api_domain'))
->middleware(['auth:api', 'api.sign.check'])
->namespace($this->namespace)
->group(function () {
Route::get('/v1/ping', function () {
return 'This Api v1';
});
});
Route::domain(config('domain.web_domain'))
->middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
// File: tests/ApiFeatureBaseTestCase.php
namespace Tests;
class ApiFeatureBaseTestCase extends TestCase
{
protected function setUp(): void
{
parent::setUp();
$this->withHeader('Host', config('domain.api_domain'));
}
}
// File: tests/Feature/ApiPingTest.php
namespace Tests\Feature;
use Tests\ApiFeatureBaseTestCase;
class ApiPingTest extends ApiFeatureBaseTestCase
{
public function testPing()
{
$this->get('/v1/ping');
}
}
Can you create a wrapper method on your ApiFeatureBaseTestCase class?
public function get($uri, array $headers = [])
{
return parent::get(config('domain.api_domain') . $uri, $headers);
}
Then in your ApiPingTest class:
public function testPing()
{
$this->get('/v1/ping');
}

The update nor the destroy methods won't work in laravel eloquent model?

I have a strange situation where eloquent model won't let me update nor destroy while index and create is working fine!
I'm using Vue.js and Laravel API Resource for form control, and while it worked with me before, it won't work here:
Here's my Vue.js Code:
updateFinish(finish) {
axios.patch(`/api/finishes/${finish.id}`, finish).then(response => {
this.fetchFinishes();
}).catch(error => {
// Get laravel validation error
this.errors = error.response.data.errors;
});
},
laravel update code (not working)
public function update(FinishType $finishType)
{
// Don't know why not working
$finishType->update($this->validateRequest());
return new FinishTypeResource($finishType);
}
the response is null:
{"id":null,"name":null}
While this code works:
public function update($id)
{
$finishType = FinishType::find($id);
$validates = $this->validateRequest();
$finishType->name = $validates['name'];
$finishType->save();
return new FinishTypeResource($finishType);
}
public function validateRequest()
{
return request()->validate([
'name' => 'required | unique:finish_types',
]);
}
Note the Model name is FinishType and database table name is finish_types, I even tried to define the table name in the model like so protected $table = 'finish_types' – still not working and I already have defined the $fillable array!!!
Your route model binding is not working correctly, for the implicit binding to work your injected variable should match the route parameter name.
Assuming that your parameter name could be finish (reading the url from your javascript) you have to write the update function using $finish as injected variable, like this:
public function update(FinishType $finish)
{
$finish->update($this->validateRequest());
return new FinishTypeResource($finish);
}
Do the same for destroy():
public function destroy(FinishType $finish)
{
// your destroy code here
}
In any case you can run php artisan route:list to find your parameter name (the part of the URI in braces) and give the same name to the injected variable.
If the two do not match, parameter and injected variable name, laravel injects a void, not loaded, FinishType model so it does not make sense doing an update or a delete on it.
I can't post comments so I'm going to post what I assume is the answer.
Laravel does route model binding automagically when the route url name corresponds to the name of the table I think... or model.
So users/{id} would auto bind the User object when you type it as a param in the controller. Example (User $user)
However, since your URL seems to be "different" from the name of your Model/Table, go to the RouteServiceProvider, and manually do the binding.
So in your case you'd do something like this in the boot function of the RouteServiceProvider class:
public function boot()
{
parent::boot();
Route::model('finishes', FinishType::class);
}
Don't forget your imports :)
You can read more about Explicit Model Binding here: https://laravel.com/docs/5.8/routing#explicit-binding

How do I send data to partial views from controller in laravel?

I have setup my navigation menu from a ViewComposer (see laravel view composers: https://laravel.com/docs/5.6/views#view-composers) like this
View::composer('partials.nav', function ($view) {
$view->with('menu', Nav::all());
});
What I need is that from some controllers to setup which navigation item is active, ie "current section".
Question:
How do I send from some controllers a variable to "partials.nav" like currentNavItem?
Do I send it with the rest of the variables for returned view?
like
return view('page.blade.php",$viewVariables + $optionalVariablesForPartialsViews);
It looks spammy
Side notes:
I use laravel 5.6
Later edit
It looks Laravel 5.1 : Passing Data to View Composer might be an options. I will try and get back .
Because the $variable you want to send differs in different controller's actions yes you need to specify the $variable
return view('page.blade.php",$viewVariables,$variablesForPartialsViews);
of course you might need to set a default value for the $variable in order to avoid undefined variable error
You should handle the parameters.
for exemple:
public function compose(View $view)
{
$view->with('page', $this->getPage());
}
public function getPage()
{
$viewVariables = 2;
$optionalVariablesForPartialsViews = 1;
return $viewVariables + $optionalVariablesForPartialsViews;
}
Under your app folder make a class named yourClassNameFacade. Your class would look like this.
class yourClassNameFacade extends Facade
{
protected static function getFacadeAccessor()
{
return 'keyNameYouDecide';
}
}
Then go to the file app/Providers/AppServiceProvider.php and add to the register function
public function register()
{
$this->app->bind('keyNameYouDecide', function (){
//below your logic, in my case a call to the eloquent database model to retrieve all items.
//but you can return whatever you want and its available in your whole application.
return \App\MyEloquentClassName::all();
});
}
Then in your view or any other place you want it in your application you do this to reference it.
view is the following code:
{{ resolve('keyNameYouDecide') }}
if you want to check what is in it do this:
{{ ddd(resolve('keyNameYouDecide')) }}
anywhere else in your code you can just do:
resolve('keyNameYouDecide'))

Implicit route, with firstOrCreate instead of findOrFail

Is it possible to create an implicit route where if it is not found the thing is created? I am using Laravel 5.5.13.
For instance this is my implicit route:
Route::post('thumbs/{player}', 'ThumbController#store');
And in my controller it is this:
public function store(Request $request, Player $player)
{
$thumb = new Thumb($request->all());
$player->thumbs()->save($thumb);
return response()->json($thumb, 201);
}
So now if I go to the endpoint of ..../api/thumb/1 it will create a thumb related with Player of id 1. However instead of a id number I wanted to provide it a string like this:
..../api/thumb/PLAYER_NAME
So example of ..../api/thumb/Blagoh, then my endpoint should first find if a player exists by name "Blagoh", and if it doesn't then it should create it. I couldn't figure this one out.
What you should do is adding into boot method of RouteServiceProvider something like this:
Route::bind('player', function ($value) {
if ($player = \App\Player::find($value)) {
return $player;
}
return Player::create(['name' => $value]);
});
It's called explicit binding and you can update logic as showed above. Reference - Route model binding

How do I access a global model instance in laravel 4?

In Laravel 4, how do I create an instance of a model and make it globally available? Even in views. I'm looking to do something similar to the way you get the User instance using Auth::User->name (the syntax I mean, not storing in a session) but in this case it would be ModelName::DefaultEntity->attribute.
A little more detail...
I am writing an application that will house multiple websites - a bit like a CMS. So I have a Website model. Each Website model will have a URL attribute so that when a user visits the URL the application can retrieve the Website model from the database and brand the website appropriately e.g. Title, logo, theme, etc...
I would like the current Website model to be available everywhere without having to create a new instance of Website in every controller/method. So in my layouts and views I could just say something like:
{{ Website::Website()->name }}
or
{{ CurrentWebsite::name }}
I have achieved the first one by making a static method in the Website model:
public static function current()
{
return Website::find(1); // just to test it for now
}
But with that, it will have to do a database query every time I say:
{{ Website::current()->name }}
Plus it doesn't feel right.
Can anyone help?
Kind regards,
Robin
You probably are looking for 'a shared container bind'. See the docs here.
<?php
App::singleton('foo', function()
{
return Website::whereCode('whoop')->first();
});
App::make('foo'); // every where you need it
Create normal class. Like CurrentWebsite or Website or whatever.
class Website {
public function a() {
//your code
}
}
Create facade (WebsiteFacade.php)
use Illuminate\Support\Facades\Facade;
class WebsiteFacade extends Facade {
protected static function getFacadeAccessor() { return 'website'; }
}
Create Service Provider
use Illuminate\Support\ServiceProvider;
class WebsiteServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('website', function()
{
return new Website();
});
}
}
4.Go to your config/app.php and add folowing:
'providers' => array(
'WebsiteServiceProvider'
)
and
'aliases' => array(
'WebsiteFacade'
)
5.Refrech auto loader. And Now you can access Website class anywhere like this:
Website::a();
What you already have is good, but if you just want prevent that query from executing every time, you can cache it:
public static function current()
{
return Website::remember(10)->find(1); // just to test it for now
}
Adding a listener to your routes.php:
DB::listen(function($sql, $bindings, $time) { var_dump($sql); var_dump($bindings); });
And executing it:
{{ Website::current()->name }}
Will show the query in the first execution but not in the second, because it's cached.

Resources