Add global method to all Eloquent Models in Laravel 5.2 - php

I want add given method to all my Eloquent Models:
public function isNew(){
return $this->created_at->addWeek()->gt(Carbon::now());
}
Is this possible to do without bruteforce?
I could not find anything in the docs
Thanks

What you can do:
Create BaseModel class and put all similar methods in it. Then extend this BaseModel class in all models instead of Model class:
class Profile extends BaseModel
Use Global Scope.
Create trait and use it in all or some of your models.

Sure, you can do that. Just simply extend the Laravel's eloquent model like so:
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
abstract class BaseModel extends Model
{
public function isNew() {
return $this->created_at->copy()->addWeek()->gt(Carbon::now());
}
}
Now your model should extend from this new BaseModel class instead:
class User extends BaseModel {
//
}
This way you can do something like this:
User::find(1)->isNew()
Note that I also call copy() method on the created_at property. This way your created_at property would be copied and won't be accidentally added 1 week ahead.
// Copy an instance of created_at and add 1 week ahead.
$this->created_at->copy()->addWeek()
Hope this help.

Related

Casting model to another model that extend the original

I'm trying to cast a model to another one that extends the same model.
Is there a build in way in Laravel this achieve this?
Example
In the code below I would like to cast User to ExtendedUser
class User extends Model
{
...
}
class ExtendedUser extends User
{
...
}

Laravel on some kind of Model Ready method

Well i don't know how to format the title of this post in very clear way, but here's my question:
Say i have
Posts::find('1);
Photos:find('1');
... and so on, every mode db request
now by default i can access db columns, for instance the id: through model->id
$Photos = Photos::find('1')->first();
echo $Photos->id; // will return 1
what i want is that i need all those kind of requests to add a custom field automatically like hashed_id, which is not in the database, which in return will make all models have a hashed_id as well, i know i can add that field to database and then grab it but i need it for different reasons/implementations
i did create a BaseModel and every Model will extend that BaseModel, so Photos extends BaseModel, BaseModel extends Model... and all that etc etc.
but i need some kind of constructor, upon retrieving data to process the data automatically without having to add -let's say- a hash_id() after retrieving the data.
something like, onAfterGet(), onReady()....sort of commands.
i hope my question is clear.
Thanks.
What you're looking for is an Accessor. Accesors can be used to add custom attributes to the model. Combine this with the $appends property and you have exactly what you need. The $appends property adds the custom accessor in every result.
You can do this by creating a base model like you've stated in the question or by using traits. I'll show you an example on how to achieve this using a base model.
Let's create base model called BaseModel. All other models that need this custom attribute will extend this.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class BaseModel extends Model
{
protected $appends = ['hashed_id'];
public function getHashedIdAttribute()
{
return some_hash_function($this->id);
}
}
We have a Image model which extends our BaseModel.
<?php
namespace App;
class Image extends BaseModel
{
}
Now every result from the Image model will have the hashed_id field added by default.
Accesor documenation https://laravel.com/docs/5.4/eloquent-mutators#defining-an-accessor
If I understand you right, all you need to do is to define mutator, for example:
<?php
class Photo extends Model
{
/* ... model implementation ... */
public function getHashedIdAttribute()
{
return md5($this->id);
}
}
Then you can access property like it was in database:
echo Photo::find(5)->hashed_id;

Laravel 5 global model methods?

I have a number of tables / models setup that have 'locked_at' and 'locked_by' columns, in essence what I would like to do is call something like:
$model->lock();
This method would check that row is not already locked, set the both cells and then save the model.
I can create the lock method inside each of my models, but that doesn't seem like the best idea. I would prefer to create the method once and have it accessible to all models.
Is there a way of doing this in laravel?
Just like ceejayoz suggested, you could achieve it by using a Trait.
Step 1
Create a folder called Traits and inside that create trait class like the following
<?php
namespace App\Traits;
trait Lockable {
public function lock() {
$this->lock = 1;
$this->save();
}
}
Step 2:
Now import the trait on your model class like the following
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Traits\Lockable;
class User extends Authenticatable
{
use Lockable;
}
Thats it! Now you could call the function like
$user = \App\User::find(1);
$user->lock();
You can create BaseModel class that extends Model and make all your models that using lock() method extend BaseModel class instead of theModel. Then just define lock() method in the BaseModel class.

How to overwrite an vendor class

How can i overwrite a vendor class?
I'm using Laravel Spark and i wanna have Uuid for all models. Due Spark manage some models inside the package and i don't see a possibility to use my own model for Notifications etc. i would like to overwrite the base Model class from Illuminate\Database\Eloquent\Model, so i could include there my uuid trait.
I tried over the ServiceProvider with:
public function boot()
{
//
$this->app->bind('Illuminate\Database\Eloquent\Model', 'App\Models\Model');
}
But it didn't worked.
Is it possible or maybe exist a better way?
Thanks for any help.
Create a custom model class which will extend the eloquent model.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CustomModel extends Model {
// Your implementation
}
And then rest of the models you extend your custom model.
class Test extends CustomModel {
}

Is there any method/way to find out all the functions of some class in laravel?

I am understanding Laravel(5.1 version although 5.2 now recently comes) framework...and studying it deeply...What I am trying to ask let me elaborate through some example: I have created the model named Blog:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model {
protected $fillable = ['title','body'];
}
Now in my controller I am accessing the function create() of this class in my controller store() method like: public function store(BlogRequest $request)
{
$input = Request::all();
Blog::create($input);
return redirect('blogs');
} As you can see that in above controller method we are accessing the static function/method create() i.e Blog::create($input) ..so the question is as there are so many other methods exists like create() method of a model(Blog) class which extends the Model class...is there any way/strategy/function to find out/know all the functions of this Model Class...
Yes! You can refer to the API documentation.
For example, I searched for model and found Illuminate\Database\Eloquent\Model, which is the class your models extend and there it is the create static method.
You can change the Laravel version on the top left and filter for classes, namespaces, interfaces and traits on the top right. Pretty neat!
Edit:
You can use the getMethods method on the ReflectionClass to list all available methods for a given class.
For example:
$methods = (new ReflectionClass('\App\Blog'))->getMethods();
dd($methods);

Categories