Laravel Model Events dont fire - laravel

I have this code on my controller
public function gracias()
{
$client = new Client;
$client->name = "name";
$client->lastname = "lastname";
$client->email = "email";
$client->phone = "phone";
$client->save();
Client::saved(function($client)
{
Log::info('on saved');
if ($client->isValid())
{
Log::info('SUCCESSFULL SAVING MODEL');
}else
{
Log::info('ERROR ON SAVING CLIENT');
}
});
Event::listen('client.create', function($client)
{
Log::info('event listen client.create');
});
and on Laravel.log I don't see the "Logs messages", the Model Events don't fire. What I'm doing wrong?
Thank you!!

A model event must be set before you actually save your models as #SamSquanch mentioned. The recommended way (not including observers) is to use the boot method.
In your case it would be like this:
<?php
class Client extends Eloquent {
public static function boot() {
parent::boot();
static::saved(function($client) {
Log::info('on saved');
if ($client->isValid()) {
Log::info('SUCCESSFULL SAVING MODEL');
} else {
Log::info('ERROR ON SAVING CLIENT');
}
})
}
public function gracias()
{
Event::listen('client.create', function($client) {
Log::info('event listen client.create');
});
$client = new Client;
$client->name = "name";
$client->lastname = "lastname";
$client->email = "email";
$client->phone = "phone";
$client->save();
}
}
This will trigger on all saves on the model. If you only want to trigger when a model have been successfully created, change static::saved to static::created.

You are setting the event closure AFTER you are calling save on the model. You should be calling save after you define the event closure.
public function gracias()
{
$client = new Client;
$client->name = "name";
$client->lastname = "lastname";
$client->email = "email";
$client->phone = "phone";
Client::saved(function($client) {
Log::info('on saved');
if ($client->isValid()) {
Log::info('SUCCESSFULL SAVING MODEL');
} else {
Log::info('ERROR ON SAVING CLIENT');
}
});
Event::listen('client.create', function($client) {
Log::info('event listen client.create');
});
$client->save();
}

Related

Laravel forget cache

Laravel 8.0 CACHE_DRIVER=file.
Stored in cache 'posts' and 'post_detail'.
I'm using full url for save in cache unique page of pagination posts.
public function __contructor()
{
$this->full_url = request()->fullUrl();
}
// ALL POSTS WITH PAGINATION
public function posts()
{
if (Cache::has("posts_".$this->full_url)) {
$posts = Cache::get("posts_".$this->full_url);
} else {
$posts = Cache::rememberForever($this->full_url, function() {
return Post::paginate(15);
});
}
}
// DETAIL POST
public function post_detail($slug)
{
if (Cache::has("post_detail_".$this->full_url)) {
$post_detail = Cache::get("post_detail_".$this->full_url);
} else {
$post_detail = Cache::rememberForever("post_detail_".$this->full_url, function() {
return Post::where('slug', $slug)->first();
});
}
}
I can forget cache only for 'post_detail' but I have no idea how to remove the cache for all posts that include the key 'posts_'
// UPDATE POST
public function update()
{
...
$post->update();
$full_url = $request->getSchemeAndHttpHost()."/".$post->post_categories->category_slug . "/" .$post->slug);
Cache::forget("post_detail_".$full_url.""); // OK
Cache::forget("posts_*"); // forget al posts contains 'posts_' key.
}
thanks

inject required dependency to a bind directly in the register method

This is my register method. I have two binds. The second CaptionOrderSubmission is the one that interest me.
public function register()
{
$clientKey = env('REV_CLIENT_API_KEY');
$userKey = env('REV_USER_API_KEY');
$endPoint = env('REV_URL_END_POINT');
App::bind('RevAPI\Rev', function($app) use($clientKey, $userKey, $endPoint)
{
return new Rev($clientKey, $userKey, $endPoint);
});
App::bind('RevAPI\CaptionOrderSubmission', function($app) use($clientKey, $userKey, $endPoint)
{
$rev = new Rev($clientKey, $userKey, $endPoint);
return new CaptionOrderSubmission($rev);
});
}
How can I do something like?
public function register()
{
$clientKey = env('REV_CLIENT_API_KEY');
$userKey = env('REV_USER_API_KEY');
$endPoint = env('REV_URL_END_POINT');
App::bind('RevAPI\Rev', function($app) use($clientKey, $userKey, $endPoint)
{
return new Rev($clientKey, $userKey, $endPoint);
});
App::bind('RevAPI\CaptionOrderSubmission', function($app) use(RevApi/Rev $rev)
{
return new CaptionOrderSubmission($rev);
});
}
is that possible?
I found the solution
in the second bind you can do
App::bind('RevAPI\CaptionOrderSubmission', function($app)
{
$rev = $app->make("RevApi\Rev");
return new CaptionOrderSubmission($rev);
});

Laravel : Model saved with autogenerated uuid but instance of this model have this uuid empty

I use a trait for generate uuid on my model. It's work because, in my database the uuid value is not empty. But the current instance of my model don't have the new value.
this is the trait :
trait UuidModel
{
public static function bootUuidModel()
{
static::creating(function ($model) {
// Don't let people provide their own UUIDs, we will generate a proper one.
$model->uuid = Uuid::generate(4);
return true;
});
static::saving(function ($model) {
// What's that, trying to change the UUID huh? Nope, not gonna happen.
$original_uuid = $model->getOriginal('uuid');
if ($original_uuid !== $model->uuid) {
$model->uuid = $original_uuid;
}
return true;
});
}
public function scopeUuid($query, $uuid, $first = true)
{
if (!is_string($uuid) || (preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', $uuid) !== 1)) {
throw (new ModelNotFoundException)->setModel(get_class($this));
}
$search = $query->where('uuid', $uuid);
return $first ? $search->firstOrFail() : $search;
}
public function scopeIdOrUuId($query, $id_or_uuid, $first = true)
{
if (!is_string($id_or_uuid) && !is_numeric($id_or_uuid)) {
throw (new ModelNotFoundException)->setModel(get_class($this));
}
if (preg_match('/^([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$/', $id_or_uuid) !== 1) {
throw (new ModelNotFoundException)->setModel(get_class($this));
}
$search = $query->where(function ($query) use ($id_or_uuid) {
$query->where('id', $id_or_uuid)
->orWhere('uuid', $id_or_uuid);
});
return $first ? $search->firstOrFail() : $search;
}
}
This is my model :
class Image extends BaseModel
{
use UuidModel;
protected $table = 'images';
public $incrementing = false;
public $timestamps = true;
protected $guarded = array('id', 'timestamps', 'path');
protected $visible = array('timestamps', 'uuid');
protected $hidden = array('id', 'path');
public function Item()
{
return $this->belongsTo('App\Models\Item', 'id', 'item_id');
}
}
This is my Controller :
class ImageController extends Controller
{
...
public function store(CreateImageRequest $request, $itemSlug)
{
$item = $this->getItem($itemSlug);
$image = new Image();
$image->path = "";
$image = $item->Images()->save($image);
return Response::json($image->uuid, 201);
}
...
}
And the response is always : {} but the uuid is not empty in my database.
UPDATE
This test works :
public function store(CreateImageRequest $request, $collectionSlug, $itemSlug)
{
$item = $this->getParentItem($collectionSlug, $itemSlug);
$image = new Image();
$image->path = $filePath;
$image = $item->Images()->save($image);
$newImage = Image::find($image->id);
return Response::json($newImage->uuid, 201);
}
i'm having the same problem yesterday, here's the working trait
trait UuidTrait
{
public static function bootUuidTrait(){
static::creating(function($model){
$model->incrementing = false;
$model->{$model->getKeyName()} = Uuid::generate()->string;
});
}
}
so maybe here's the answer on your problem
static::creating(function ($model) {
// Don't let people provide their own UUIDs, we will generate a proper one.
$model->uuid = Uuid::generate(4)->string;
return true;
});
i hope i would help someone :D
You are hooking onto "creating" and "saving" events, but what you should be doing is hooking onto "creating" and "updating" events.
If you check official documentation it says that "saving" event is triggered on both creating a new model and updating an existing one - so in your case it gets called when creating new model and thus leaves "uuid" value on previous one (which is nothing); and also when updating it's the same thing.
If you switch to "creating" and "updating" events then everything will work as you want it to - basically just replace "saving" with "updating" and that's it.

Laravel 5 controller returns controller

i have a controller function that needs to be redirected to a route with a different function to avoid redundancy of codes. is it possible to put a redirect to a different function?
Here is the code:
public function index()
{
$x = Auth::user()->id;
$id = DB::table('requests')->where('id', $x)->lists('userid');
if (!is_null($id)) {
$frnd = DB::table('users')->whereIn('id', $id)->get();
if (!is_null($frnd)) {
return view('friendlist', compact('frnd'));
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
}
public function respond()
{
$frnds = new Friend;
$id = Auth::user()->id;
$friendid = Request::input('friendid');
$frnds->id = $id;
$frnds->friendid = $friendid;
if (Input::get('accept')) {
$frnds->save();
}
DB::table('requests')->where('id', $id)->where('userid', $friendid)
return // this is where i should redirect to page with function index()
}
Name the index route in routes definition like this
Route::get('home', ['uses' => 'YourController#index', 'as' => 'home']);
Then use redirect method to redirect to this route:
return redirect()->route('home');
For more info on redirects use official docs
http://laravel.com/docs/5.1/responses#redirects
I don't think is a perfect, but someone prefer this way:
private function _index()
{
$x = Auth::user()->id;
$id = DB::table('requests')->where('id', $x)->lists('userid');
if (!is_null($id)) {
$frnd = DB::table('users')->whereIn('id', $id)->get();
if (!is_null($frnd)) {
return view('friendlist', compact('frnd'));
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
} else {
$frnd = null;
return view('friendlist', compact('frnd'));
}
}
public function index()
{
$this->_index();
}
public function respond()
{
$frnds = new Friend;
$id = Auth::user()->id;
$friendid = Request::input('friendid');
$frnds->id = $id;
$frnds->friendid = $friendid;
if (Input::get('accept')) {
$frnds->save();
}
DB::table('requests')->where('id', $id)->where('userid', $friendid)
$this->_index();
}
private function for repeated code.

Laravel library to handle messages

I have just created a library class in laravel.
class Message {
public static $data = array();
public function __construct() {
// If session has flash data then set it to the data property
if (Session::has('_messages')) {
self::$data = Session::flash('_messages');
}
}
public static function set($type, $message, $flash = false) {
$data = array();
// Set the message properties to array
$data['type'] = $type;
$data['message'] = $message;
// If the message is a flash message
if ($flash == true) {
Session::flash('_messages', $data);
} else {
self::$data = $data;
}
}
public static function get() {
// If the data property is set
if (count(self::$data)) {
$data = self::$data;
// Get the correct view for the message type
if ($data['type'] == 'success') {
$view = 'success';
} elseif ($data['type'] == 'info') {
$view = 'info';
} elseif ($data['type'] == 'warning') {
$view = 'warning';
} elseif ($data['type'] == 'danger') {
$view = 'danger';
} else {
// Default view
$view = 'info';
}
// Return the view
$content['body'] = $data['message'];
return View::make("alerts.{$view}", $content);
}
}
}
I can use this class in my views calling Message::get(). In the controllers, I can set the message as Message::set('info', 'success message here.'); and it works perfectly fine.
However, I can not use this class for flash messages redirects using Message::set('info', 'success message here.', true). Any idea, whats wrong in this code?
First problem is the constructor function is not called when using the above get and set methods, with minor modification the code is now working. :)
class Message {
public static $data = array();
public static function set($type, $message, $flash = false) {
$data = array();
// Set the message properties to array
$data['type'] = $type;
$data['message'] = $message;
// If the message is a flash message
if ($flash == true) {
Session::flash('_messages', $data);
} else {
self::$data = $data;
}
}
public static function get() {
// Check the session if message is available in session
if (Session::has('_messages')) {
self::$data = Session::get('_messages');
}
// If the data property is set
if (count(self::$data)) {
$data = self::$data;
// Get the correct view for the message type
if ($data['type'] == 'success') {
$view = 'success';
} elseif ($data['type'] == 'info') {
$view = 'info';
} elseif ($data['type'] == 'warning') {
$view = 'warning';
} elseif ($data['type'] == 'danger') {
$view = 'danger';
} else {
// Default view
$view = 'info';
}
// Return the view
$content['body'] = $data['message'];
return View::make("alerts.{$view}", $content);
}
}
}

Resources