Eloquent (without Laravel) caching implementation - php

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.

Related

Laravel what is use HasFactory?

I created a model in Laravel. I always noticed the default would be use HasFactory. May I know what exactly does it work. In my understanding from reading documentation, it is for linking to database (I guess?) But I still don't understand how it works exactly.
HasFactory is not to link to the database.
It is a trait that links a Eloquent model to a model factory.
Factories are normally used in testing when wanted test-data for a specific model.
You can read more about factories in Laravel here: https://laravel.com/docs/9.x/database-testing#model-factories and here:
https://laravel.com/docs/9.x/eloquent-factories
The trait ensures that you can instantiate a factory like this:
User::factory()->create();
In older versions of Laravel the trait was not used, and instead a factory had to be instantiated by the global factory helper like this factory(User::class)->create(); but that caused a lot of problems with intellisense in IDE's.

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 Magento Collections with External DB

I'm trying to access data on a external DB from magento from a Module, while using Magento ORM capabilites, I was able to do so by extending the:
Mage_Core_Model_Abstract and Mage_Core_Model_Resource_Db_Abstract classes as shown on this page:
http://www.solvingmagento.com/accessing-an-external-database-from-your-magento-module/
However when I'm try to use the getCollection() method on my model and I get "false" so I'm wondering if you can create collections based on the "Mage_Core_Model_Resource_Db_Abstract" class, I tried with "Mage_Core_Model_Resource_Db_Collection_Abstract" without any luck.
If it's not possible, does that mean that I have to change my module and use:
Mage_Core_Model_Mysql4_Abstract instead of Mage_Core_Model_Resource_Db_Abstract
As it seems like it has a "Mage_Core_Model_Mysq4_Collection_Abstract" class that works for what I want to do, as shown in:
http://fishpig.co.uk/magento/tutorials/create-external-database-connection/
I was trying to avoid Mage_Core_Model_Mysql4_Abstract as it sounds to me that it's exclusive for MySQL and I was hoping to keep the code more flexible.
Thanks,

Global model initialization in Kohana

I'm new to Kohana and bumped into the following problem:
I have 3 models, model1, model2, model3. Every time I want to use a method from one of the models (in a different controller method / model) I have to
$model1 = New Model_Model1();
In a controller, I can do a public $model1 and create the model in the constructor, that's OK. In a model, however, I managed to get an infinite loop of model initialization.
In CodeIgniter, it's easy: I can autoload models. How do I make my models globally accessible in Kohana so that I could $this->model1->dosth(); from anywhere, without worrying about creating multiple instances of the same model?
First of all, the only reason you can do $this->model->method() in CodeIgniter is because it has a super object;
In Kohana you can create an instance method in your model and simply call Model::instance() ... if you need a global instance. If you need to access them in controllers only then you can override the default controller, load your models in the constructor and use them in your child controllers.
It all depends on your situation really. Loading a new model instance isn't always a bad thing.

Relations in your model in a MVC application?

Now I have an model User which represents an user in the application. And I use an UserRepository with methods like getById($id) and getAll().
An user can post reviews. If I want to show the 5 or 10 or maybe 20 last reviews of an user it's most logical to ask the user I think. So I would have a method $user->getLastReviews(5).
But what's the best way to implement this? Give each user an instance of the ReviewRepository (with a method $reviewRepository->getByUser(User $user) for example)? Or are there better ways?
I think it's fine to have models contain and use instances of other models, so your way is fine, to have User model contain an instance of the Review model, and let that Review model handle the logic of getting said reviews.
Also, you could add a method to the UserRepository to handle it like so:
class UserRepository extends Model{
$review = new reviewRepository();
function getReviews($numOfReviews){
return $this->review->getReviews($user_id);
}
Another option would be to create a repository method where you passed in both variables. Something like $reviewRepository->getLastReviewsByUser(5, $user).
Usually this is a job for the ORM. Almost every framework uses one implementation (ie. Doctrine for PHP/Symfony or Hibernate for Java) but naturally you can implement your own ORM (ORM are often implemented using introspection).
Once you have an ORM library you define relations between Models in a "setup phase" (in your case you'll have "user has many reviews"). Then you'll use the ORM methods which knows how to deal with those ones (often relations are mutual ie. "review belongs to user"). The concept is that this setup phase will discharge you from dealing with issues like the one you pointed.
My suggestion is to use one of the already existing ORM implementations which already supplies facilities for getter and setter methods of related Models. In the other case, you have to write specialized getters and setters by yourself for every Model.

Categories