separating relationships and model functions in Laravel - php

Everytime I'm writing a Laravel model it just gives me a feeling of messy code. I have relationships and other model functions specially when using domain driven design. So I though about separating relationships and functions.
Example I have a User class that extends Eloqeunt:
class User extends Eloquent{}
and inside this class I have register functions and password hashing functions etc. Also, we can declare the relationships so:
class User extends Eloquent{
function post(){
return $this->hasMany('POST');
}
}
For some reason this smells funky to me. My solution was to create a Entities folder and inside create a User folder which will hold 2 files one would be UserRelationship which would hold of the the relationships for this class:
class UserRelationship extends Eloquent{
function post(){
return $this->hasMany('POST');
}
}
and a second which would be the actual User class where I would write all of the functions and this class would extend the UserRelationship class instead of Eloquent:
class User extends UserRelationship{
public static function register($email, $password, $activate_token)
{
$user = new static(compact('email', 'password', 'activate_token'));
$user->raise(new UserWasRegistered($user));
return $user;
}
}
What do you guys think of this approach I am relatively new to all this so I don't know if this is bad practice or to much work for little reward. What do you guys recommend?

For a user model, it is too much work. The easiest way and still a better approach is to define the relationship in the user model. If for example it is a post model where you have relationships for post to "user, comment, reply etc" then you can attempt splitting your relationships

Related

Laravel 5.1 - Dry on same characteristics models

In my Laravel 5.1 App I have a lot of aux Models with the same structure. I was thinking in the posibility of make one model and controller for using all of them, but I cannot figure how to do.
I explain, all the database aux tables have the fields ID and name, and are made for CRUD operations and for filling the forms all over the App.
Is possible to specify the table on the methods implemented by Laravel? I mean, stablish the table on construct, on get(), etc. This would made the work a much more simple if I could do AuxTable::create("sex") or even in requests like $request->auxtable("studies")->get().
Am I explaining?
you can do it with single model like below in Model class there is a method called setTable($table) which can set the table name you want to use so consider below
use Illuminate\Database\Eloquent\Model;
class AuxTable implements Model {
//other class properties
}
in your controller use the model like below
class SampleController extends BaseController {
public function index() {
$model = new AuxTable;
$model->setTable('sex');
$model->get();
}
}
this should do the trick

Is it a good practice to extend Laravel models more than one layer?

I'm reworking a project on Laravel 5.1
What I realize is that the old classes have become much complicated and do not really follow the 'single responsibility' principle anymore.
So I'm planning to do such:
<?php
class User extends Model
{
}
class SocialUser extends User
{
}
So I have a few questions,
Is it possible to achieve that?
If yes, then does the SocialUser class link back to the same database table which is Users and would it conflict with the User model itself?
Is this all a good design practice at the first place? Or I better make use of traits?
Thank you.
What you’re doing (extending the User model) is perfectly fine, and an approach I use myself in projects.
For example, if an application I’m building has shop-like functionality, then I may create a Customer model that extends my User model, and contains say, order-related relations:
class Customer extends User
{
public function orders()
{
return $this->hasMany(Order::class, 'customer_id');
}
public function worth()
{
return $this->orders()->sum(function ($order) {
return $order->total();
});
}
}
In a recent project, I’ve been working on email campaign functionality and created a Recipient class that extends the User model to add campaign-related methods:
class Recipient extends User
{
public function campaigns()
{
return $this->belongsToMany(Campaign::class, 'recipient_id');
}
}
Because both of these classes extend the User model, I get all of those (and Eloquent) methods:
$customers = Customer::with('orders')->get();
So long as you set the table in your base User model, any classes that inherit it will use that same table, even though the model may be named differently (i.e. Customer, Recipient, Student etc).
IMHO I would go for the Repository pattern. It make's a lot of sense in your situation.
I would do the following:
interface UserRepository {
public function find($id);
public function getAll();
public function create(array $attributes);
public function destroy($id);
//you get the point
}
class CoreUserRepository implements UserRepository
{
//implement the interface rules
}
class SocialUserRepository extends CoreUserRepository
{
//implement the specific logic related to a SocialUser
}
Update
As Mjh described in the comments simply implementing the interface on all UserTypeRepository caused repetition - probably not what you want!
By extending your CoreUser you avoid repetition & maintain a design that will work for your situation.
Although, in your case it could be argued that you are still following SRP because everything in the User model is relating to a user, it's only the type of user which is differing.
Why go for the Repository Pattern?
You are ensuring you have a contractual agreement that all User
Repositories need to implement.
Code is easier to maintain.
Business and data access logic can be tested separately
Should you extend your User model?
Here you are in danger of model pollution. While you can do anything with a model - not everything is a good idea.
Defining relationships on this approach would be a headache due to the confusion caused.

Laravel Eloquent Relationships with Repository/Service Design Pattern

I am currently working on a web app that has been set up using the Repository/Service Layer Design Pattern, i.e. I have service layer that does any necessary business logic before running any methods within the repository. I have facades for each one of my models which access their respective service layers, and this has been fine for the most part. However, now that I am trying to set up Eloquent relationships, the facades seem to be causing a massive headache as I am not sure which direction I should be going.
Take the following code:
class Account extends Eloquent {
// Our table name
protected $table = "accounts";
// Our primary key
protected $primaryKey = "id";
/**
* Role Relationship
*
* Returns a list of roles associated with
* this account
*/
public function roles() {
return $this->hasMany('Role');
}
}
This will not work as is, because instead of using the entity class of Role, it is using the Role Facade. I have figured out a workaround for this, by setting an alias for the Entity with a slightly different name, such as RoleEntity so that
public function roles() {
return $this->hasMany('RoleEntity');
}
will work, however this doesn't seem like the most optimal solution.
My question is, is the practice ok? Or better yet, should this be happening at all? And if not, how do I fix it/where did I go wrong?
You have two classes with the same name in the same namespace. Use different namespaces so you can use the same class names.
I usually use \Models to locate my models classes.
At the top of each model file:
namespace Models;
In your controller or any part of your app:
\Models\Role::first();
Note that changing the namespace on your model will require you to add the namespaces of other classes i.e. Str, Eloquent, Url, Redirect, etc.
use Eloquent;
use URL;
In your model, you also have to pass the namespaces in the relationship functions, i.e.:
public function roles() {
return $this->hasMany('\Models\Role');
}

eloquent ORM controller or model

I am writing a web application, and I am a self proclaimed disorganised developer, I write things quickly and worry about maintenance later. I am working with laravel at the moment, I have quite alot of database interaction, all the examples of eloquent seem to interacting with database object directly in the controller. Is this the best option, or is it more organised to wrap these eloquent methods in a function in the Model for that relevant query. e.g.
class HomeController extends \BaseController {
public function index()
{
$user = User::find(1);
return $user;
}
}
would this be better served as,
class HomeController extends \BaseController {
public function index()
{
$user = new User;
$result = $user->getSingleUser(1); //Being a method in the User.php model
return $result;
}
}
I realise this is very very basic example, but for organisational purposes is it best to seperate the database and "business logic" away from the controller?
but for organisational purposes is it best to seperate the database
and "business logic" away from the controller?
Yes
would this be better served as,
Yes - you should separate your logic into the correct areas, to make the code more manageable.
That's why MVC pattern is for. Store your db requests deep inside, also you can separate your model layer from db layer if you wish. If you more decouple your application structure then more manageable is your code.

The M of MVC (ZF)

I don't get it how it really works.
I have a database table user and a model User:
<?php
class User extends Zend_Db_Table_Abstract {
protected $_name = 'users';
}
And in the controller I call it: $user = new User()
But how do I get for example all users or a user with the id: 1?
Zend_Db_Table implements the Table Gateway pattern and the associated Zend_Db_Table_Row implements the Row Data Gateway pattern.
This means that as the table class represents your database table, it makes more sense to use a plural class name. Similarly, a singular class name should be used for the row class.
Hence you end up with something like this:
class Model_Users extends Zend_Db_Table_Abstract
{
protected $_name = 'users'; // database table name
protected $_rowClass = 'Model_User'; // row class name
public function fetchAllInLastNameOrder()
{
return $this->fetchAll(null, array('last_name', 'first_name'));
}
public function fetchUserById($id)
{
return $this->_fetchRow('id = '. (int)$id);
}
}
class Model_User extends Zend_Db_Table_Row_Abstract
{
public function getFullName()
{
return trim($this->title . ' '
. $this->first_name . ' '
. $this->last_name);
}
}
The point of creating your own classes is that you can add your own methods that your controllers and views can then use. You should never use the Zend_Db_Table methods directly other than in your model classes. This is because this model design is tightly coupled to the database implentation. Over time, you may find that this isn't flexible enough and want to use a different system. If you have ensured that the rest of your application only ever accesses methods created in Model_Users and Model_User then you should be able to reimplement your model without breaking the rest of your app...
For larger applications and ones with complex business logic, it is rare for a model to be a simple wrapper over a single database table. For better flexibility and maintainability, you can consider creating models which are simple classes and then using a mapper class that maps from the model to the database. This is explored by Matthew Weier O'Phinney in his talk Architecting Your Models, which I highly recommend looking at.
Also, for ideas on how to use the model from within the controller, the Quick Start or my tutorial are good starting points.
Are you looking for $user->find()?
Also, Zend_Db_Table != Model. You can read more about the M of MVC here:
Model Infrastructure
Zend Framework: Surviving the Deep End
Writing Robust PHP Backends with Zend Framework
Try creating a static method in your User class that returns an array of all users.

Categories