Can I use an Eloquent model as a fully featured class? - php

I'm just learning Laravel 4 and I was unsure about how Eloquent models work. It is clear to me that they are a good way to interact with the database but can I define constructors and functions on a class that extends Eloquent to use it for more than database interaction?

Yes! A class that extends Eloquent, doesn't make it a class solely used for Eloquent purposes. You've got the realize the concept of class extension. Class extension is there to simply add features to ANY class from another, existing class. In this case Eloquent.
You can take any model you already have, and tomorrow decide that you want to use it with Eloquent and simply extend it. Your original class is still your original class and works the same. Any methods or properties in the original class will ovewrite its parent (Eloquent) if the parent has something with the same name.
In fact, creating other methods in a class that extends Eloquent is the real way to create robust models that do all sorts of cool stuff. I create methods in my User model for example, to calculate how many day's until their birthday. Instead of pulling the birthday column into a controller then using PHP to do the calculation, I just have a method like User::daysUntilBirthday();
If you use a constructer and extend Eloquent, make sure you still fire off Eloquent's constructor as well though.
class MyModel extends Eloquent {
public function __construct($attributes = array(), $exists = false)
{
parent::__construct($attributes, $exists); // This will fire off Eloquent's constructor.
// Your construct code.
}
}

Related

Laravel Eloquent relationships with Extended Models

I'm working on a site that has extended Models, eg.
class Asset extends Model {
public function project() {
return $this->belongsTo(Project::class);
}
}
class Video extends Asset {
}
Do I need to establish the same belongsTo Eloquent relationship with the extended class, or by virtue of the parent class having it, will Laravel do the rest?
Additionally, is there any documentation anywhere that goes into detail about how to structure such relationships (ie. in terms of Controllers)? I can't find anything on the (usually excellent) Laracasts website.
You don't need to instance the extended method twice, unless you want to override it with a different behaviour.
I personally use a lot of inheritance in my applications, and it works just as you would expect, every relation keeps working and querying using the parent default values or the specific protected variables you declare.
For example, if you declare a protected $table = 'foo', the child will also take that variable to perform its query, or you could override it on the child to query a different table from the parent.
In terms of documentation, the reason you are not finding much information I think it's because this is more a PHP and OOP issue than a framework specific one.
If you want to declare polymorphic relations, which are a really common way to implement multiple inheritance in your SQL, Laravel has your back, with specific Eloquent relations and migration commands, like $table->morphs('asset');.
Hope this helps you.

Eloquent (without Laravel) caching implementation

I am using Eloquent without Laravel and I'm wondering if there's a method which can be used (and does not rely on Laravel components) to integrate a caching method which then automatically caches all model queries (caching backend can be variable, say APCu or memcache).
I'm thinking that it should be possible to write a model base class which handles this but I'm not quite sure how I would go about implementing this. Does anybody have any ideas in this direction?
If you want to auto cache your query, you have to override the find(), findOrFail() , where() ... methods
Because of how Eloquent is built you can't simply add a method find() in your custom model class
https://laracasts.com/discuss/channels/eloquent/override-find-method/replies/72028
class MyCacheModel extends \Illuminate\Database\Eloquent\Model
{
// override methods as explained in previous link
// cache the result in redis for how long you want
}
Then in your model instead of extending Eloquent\Model, extends now from your MyCacheModel. With a bit of customization you can set how long queries will be cached and if a model shouldn't be cached then just use the Eloquent\Model.

How to create Laravel Model without Eloquent?

As I am not sure, is it possible to create models with DB Class instead of Eloquent? I want to stay away from ORM.
Thanks
Yes of course its possible. You dont need to extend any class to make a model class that encapsulates business logic and consists of methods calling the DB class.
Just create your model inside app/models/MyModel.php like this
class MyModel{
public static function getMyData(){
return DB::table('users')->select('column')->get();
}
}
then you should be fine to call your new class statically:
$data = MyModel::getMyData();
If you wanted to extend the DB class you could, though more likely you would be looking to extend the Database/Builder class to extend functionality but this is a complex topic and I suspect you would have asked a very different question if this was what you were after.
As I final note, I wouldn't steer clear of Eloquent, it's the greatest thing about Laravel amongst a lot of other great things
Just remove the "extends Eloquent" and build the queries using the DB class.

Using Fluent in a Model

I would like to know how to use Fluent Query Builder in a model? I cannot find any example on how to do it properly. All examples are using Eloquent ORM. From laravel's documentation, to create Eloquent model is by extending Eloquent class :
class User extends Eloquent {}
I understand Eloquent can be great but I am new to laravel right now and all Eloquent is doing is it's confusing me. How would I write the model? so that i can use it in my controller?
I come from codeigniter where I would write
class some_model extends CI_Model {}
and i was able to easily autoload this model into my control and take advantage of it. How is it done with fluent?
The Eloquent ORM extends Fluent, so all the fluent methods are available. Eloquent is just like some syntax sugar. I suggest you get used to it, it will keep your code cleaner.
Heres a example:
// Fluent query builder
DB::table('users')->where('id', '=', 1)->first();
// Eloquent
User::find(1);
// Generated SQL
select * from users where id = 1 limit 1;
Both generate the same SQL, and behind the scenes Eloquent is using Fluent. The main difference is that using Eloquent requires you to have models that extend the Eloquent model.
The important thing to understand is that Eloquent methods are available to you ONLY if you extend the Eloquent class. The fluent query builder methods are always available to you as long as you have specified a correct database for your application.
So why use Eloquent at all?
As in the above example Eloquent and Fluent generates the same SQL, but theres still major differences in the returned result when the response is more complex.
The Fluent query builder will return a "simple" response with just the values, theres no methods available. This is depending on your PDO settings.
Eloquent will do much more for your. You get methods available to you that comes straight from the Eloquent model. Theres also one great benefit here, Eloquent will return a collection that implements has many useful interfaces. This means you can do a lot with the returned data.
Heres some good reads:
Whats eloquent and Fluent?
Eloquent collections
Well, you can just use it like the docs are displaying. Example:
<?php
class Foobar extends Eloquent
{
public static function retrieve($code, $language)
{
return static::where('code', $code)->where('language', $language)->first();
}
}
$foobar = Foobar::retrieve('code', 'EN');
I'm using static::where because this is a static method. (no shit, Sherlock (-: )
You can also just use $this->where() or any other method then where() if the model is initialized. link to query builder docs

Going around the fact that ORM Class already extends DB Class and you need it to extend from Abstract class

My problem has to do with PHP, but it could potentially relate to any other language with an object relational mapper.
Say I have a class Event that extends DbObject and Exception that extends DbObject but I want them both to extend from Abstract Class TimePeriod. Both objects being ORM objects.
Why? Because I don't want to manually code getStartTimeStamp() on each type of class that has a start and end date.
Right now I am using interfaces but I feel like it really hurts the DRY of it.
Do I simply redesign it such that Abstract Class TimePeriod extends Dbobject and implement each object extend from it? Or is there a better solution?
The general solution to the multi-inheritance problem you are facing is aggregation/composition.
It also makes your design clearer. Exception can't be a time period after all.
So what you want is to create a TimePeriod class and pass objects of that class to Exception and Event.
Then you can either call getStartTimeStamp() on the time period object directly like that:
$event->getTimePeriod()->getStartTimeStamp();
Or create wrapping methods and calling them instead.

Categories