问题
I have an Observer
set up to Listen to a Model
's events in order to keep my Controller
clean of Logging messages. My implementation is as follows:
First, a store method that does just what it's supposed to do. Create and save a new model from valid parameters.
# app/Http/Controllers/ExampleController.php
namespace App\Http\Controllers;
use App\Http\Requests\StoreExample;
use App\Example;
class ExampleController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
/**
* Create and save an Example from validated form parameters.
* @param App\Http\Requests\StoreExample $request
*/
public function store(StoreExample $request)
{
Example::create($request->validated());
return back();
}
}
The StoreExample
Form Request isn't important. It just validates and checks a gate to authorize the action.
The Observer
I have set up logs this action.
# app/Observers/ExampleObserver.php
namespace App\Observers;
use App\Example;
class ExampleObserver
{
public function created(Example $example): void
{
\Log::info(auth()->id()." (".auth()->user()->full_name.") has created Example with params:\n{$example}");
}
}
The problem I have, is the way my logs depend on the auth()
object to be set. Given the auth
middleware and the gate it has to check in order to store an Example, there is no way a guest user will set off this code.
However, I do like to use tinker
in my local and staging environments to check the behavior of the site but that can set off an error (Well, PHP notice
to be more precise) because I can create Example
models without being authenticated and the logger will try to fetch the property full_name
from the non-object auth()->user()
.
So my question is as follows: Is there a way to catch when I'm specifically using the Laravel tinker
session to handle my models in the Observer class?
回答1:
Okay, replying to my own question: There IS a way. It requires using a Request
object. Since observers do not deal with requests on their own, I injected one in the constructor. request() can be used instead, so no DI is needed.
Why is a Request important?
Because a request object has an accessible $server attribute that has the information I want. This is the relevant information I get by returning a dd($request->server)
(I'm not gonna paste the whole thing. My Request's ServerBag has over 100 attributes!)
Symfony\Component\HttpFoundation\ServerBag {#37
#parameters: array:123 [
"SERVER_NAME" => "localhost"
"SERVER_PORT" => 8000
"HTTP_HOST" => "localhost:8000"
"HTTP_USER_AGENT" => "Symfony" // Relevant
"REMOTE_ADDR" => "127.0.0.1"
"SCRIPT_NAME" => "artisan" // Relevant
"SCRIPT_FILENAME" => "artisan" // Relevant
"PHP_SELF" => "artisan" // Relevant
"PATH_TRANSLATED" => "artisan" // Relevant
"argv" => array:2 [ // Relevant
0 => "artisan"
1 => "tinker"
]
"argc" => 2
]
}
So there's all these attributes I can filter by using $request->server('attribute')
(returns $request->server->attribute
or null
, so no risk of accessing an undefined property). I can also do $request->server->has('attribute')
(returns true
or false
)
# app/Observers/ExampleObserver.php
namespace App\Observers;
use App\Example;
class ExampleObserver
{
/* Since we can use request(), there's no need to inject a Request into the constructor
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
*/
public function created(Example $example): void
{
\Log::info($this->getUserInfo()." has created Example with params:\n{$example}");
}
private function getUserInfo(): string
{
// My logic here.
}
}
来源:https://stackoverflow.com/questions/56069090/is-there-a-way-to-catch-when-im-using-a-laravel-tinker-session-to-fiddle-with-t