Yii: add prefix/postfix to model class naming - php

Is there any way I can get Yii to work with models that have a prefix or postfix in their class name?
For example, I have a table user, which corresponds to the model User. Now, I want this model to have a prefix, say, EmulatedUser. Is there any way to achieve that without renaming my table?

The table and class name don't have to be the same. You can override the tableName in your model:
<?php
class EmulatedUser extends CActiveRecord {
public function tableName() {
return 'user';
}
}

Related

Laravel Model Extending

I have a question about models structure.
I created a model called User.php
Than I would like after get a record from DB initialize another class which extends User class based on the value from DB. I.e. there is a record from DB users
id = 1
name = John
type = 1
If type = 1 I would like to init some other class, i.g. Admin
And folders structure will be
Models
- User.php
- UserTypes
- Admin.php
How it's possible to realize this?
Thanks
You can achieve that by using for polymorphic relation. Let's say a user can be extended by two models "Admin" and "Marketer", they will look something like that:
class Admin extends Model
{
public function user() {
return $this->morphOne('App\User', 'extendable');
}
}
And the User model:
class User extends Model
{
public function extendable() {
return $this->morphTo();
}
}
Of course you will also need to add two columns to your User model extendable_id and extendable_type to hold the relation.
To read more you can check laravel documentation https://laravel.com/docs/5.5/eloquent-relationships#polymorphic-relations

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 Inheritance - Auto instantiate by database field

I have the following classes:
abstract class File extends Eloquent {
protected $table = 'files';
}
class LocalFile extends File {
}
class RemoteFile extends File {
}
I only have files table, LocalFile or RemoteFile table doesn't exists. files table has a type field with has the either App\LocalFile or App\RemoteFile stored.
Is there a way to auto cast the file's subclass during a find?
Note:
I have other models implemented with morph, but I can't see use of morph here.
Sounds like you're after global scopes. These allow you to apply a scope to a model for every query that is done using the model. https://laravel.com/docs/5.2/eloquent#global-scopes
You could apply a global scope to both of your models so that RemoteFile only looks at type === 'App\RemoteFile' and vice-versa for the LocalFile model

Eloquent doesn't get the "belongsTo" item

I have the Project model and the Contract model. When i execute Project:all() it gets me only the projects without the contract, same for contract. I tried to dd() inside contract and doesn't do anything, like is never executed. I also tried with App\ prefix and without.
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
protected $table = 'project';
public function contract() {
return $this->belongsTo('Contract');
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class Contract extends Model
{
protected $table = 'contract';
public function project() {
return $this->hasMany('Project', 'ContractID', 'ContractID');
}
}
I try to retrieve them like this:
$projects = Project::all()->take(10);
You have a few problems here.
Project::all()->take(10);
This only returns a collection of projects. You havent specified that you want the contracts also.
$projects = Project::with('contract')->get();
In your belongsTo - You havent specified the column that the table should join on. You need to do this, because you have not used a standard id for primary key and contract_id for foreign key.
unrelated to specific question, but your relationship in contract model is also wrong.
public function project() {
return $this->hasMany('Project', 'ContractID', 'ContractID');
}
If one contract has many projects, then your public function project() should be public function projects();
Finally - Why are you using non-standard table / column naming conventions? What's wrong with contract_id? Are you aware that mysql is non-case sensitive? Also the project table could be renamed projects and the contract table could be renamed contracts. It will make you writing your eloquent relations much easier and makes more sense!
If you used standard naming conventions, then you could just do this to declare your model relations.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Contract extends Model
{
public function projects() {
return $this->hasMany('Project');
}
}
Notice you dont need to specify the table name in the model, or how the table is related to the Project.

How to generate database table models with Gii in Yii?

Problem:
I used gii to generate database table models. So If I have any change in users table structure, I used gii and all my relations and other methods are removed from class. So I need to make backup of class and regenerate class and bring back other methods and relations.
Possible Solution:
I changed my class into two classes like this for a table 'users':
class Users extends UsersMapper {
public function tableName() {
return 'users';
}
public function rules() {
.....
}
public function relations() {
.....
}
}
class UsersMapper extends CActiveRecord {
public function getAllUsers() {
......
}
public function getBlockedUsers() {
......
}
}
Question:
Above method is working for me and I am using only Users class everywhere in my code. Is it valid method or there is any problem with this logic. Is there any other method.
Thanks
The Giix extension will create a models/Users class and a models/_base/BaseUsers class for your case. The Users class extends the BaseUsers class. Thus only the BaseUsers class needs to be regenerated on changing the database. It also comes with a couple of extra methods that I use quite a lot.

Categories