kohana add column to inherit model - kohana-orm

I was wondering how to work with kohana orm and inheritances.
Supose I have a model called Vehicle
$_table_columns with 5 columns
The lets supose I create another model called Car and I want to add 5 more columns to the model. How should I modify the parent $_table_columns variable or should I override it?
Thanks

I suppose you're looking for something like this protected $_table_columns = parent::_table_columns + array(...);. Unfortunatly PHP won't allow for this, so you will have to either override $_table_columns and list all 10 columns or override ORM reload_columns method like this:
public function reload_columns($force = FALSE)
{
$this->_table_columns = parent::_table_columns + array(...);
parent::reload_columns($force);
}

Related

Laravel custom belongsTo dynamic binding

I have 2 models, Building and Apartment. Building has a column named address and apartment has a column named addresss
I want to add relation like this:
public function building() {
return $this->belongsTo(Building::class, 'addresss', 'address');
}
But then this gives null:
Apartment::first()->building
Even if this works:
Apartment::first()->building()->first()
So what should I do to get it to work using only this:
Apartment::first()->building
If i kept it right the Apartment is part of the building?
That is why you set the Relation in Model Apartment:
public function building() {
return $this->belongsTo(Building::class, 'addresss', 'address');
}
When i use the belongsTo Relation, I just mention the class and do not append anymore inside the brackets like in this case:
public function user()
{
return $this->belongsTo(User::class);
}
What is the purpose of mentioning appartment's addresss aswell in the relation ? Have you set the foreign key's propely & set a hasMany Relationship in the Building-Model ?
Regards.
The issue was I had a column in apartments table named building, removing this fixed it

How can I access both of tables'fields in leftJoin in Yii2

I need tour's fields but below code just get tourPackage's fields and I have to use Active Record.
I know I have to use property in another model for fix this problem but I don't want use property because there are a lot of fields or property.
How can I get tour's table data ?
$models = TourPackage::find()->select(['tour.*'])->leftJoin('tour', 'tour.id=tour_package.tour_id')->all();
Your using TourPackage object ,
so you can't get attributes of Tour model.
If you want to get Tour model attributes,please try asArray()
ex.
$models = TourPackage::find()->select(['tour.*'])->leftJoin('tour', 'tour.id=tour_package.tour_id')->asArray()->all();
Now you will get Tour model attributes.
In TourPackage you need to define public attributes, that you will join from Tour.
For instance if you have column number in tour, then you can write:
class TourPackage extends \yii\db\ActiveRecord
{
public $number
// ..and other properties you take from tour
in TourPackage class, and add the following select in Query:
$models = TourPackage::find()->addSelect(['tour_package.*', 'tour.number AS number'])->leftJoin('tour', 'tour.id=tour_package.tour_id')->all();
Of course, you can write addSelect(['tour_package.*', 'tour.*']), but in that case tour columns with similar name will override tour_package columns.

Add WHERE condition to all SQL requests in Laravel

I'm creating an online tool for companies that each have a set of users in Laravel.
When a user is connected, he has a $connected_company_id variable
For every SELECT request (called by ::all(), find(), ...), i would like to add the condition: where company_id = $connected_company_id. I have found this post: laravel set an automatic where clause, but it doesn't work by overriding newQuery().
For every INSERT request, i would like to add the company_id.
Is this possible without changing my code inside all the controllers ?
I thought about extending Eloquent with customEloquent, and then make my models extend customEloquent, but I don't know how to write the code for customEloquent and if it could work.
Well, you could make use of the Eloquent Model Events. I assume you have the connected_company_id stored in the Session company_id
class BaseModel extends Eloquent{
public static function boot(){
parent::boot();
//Column to inject when inserting
static::creating(function ($obj){
$obj->company_id = Session::get('company_id');
});
//Column to inject when updating
static::updating(function ($obj){
$obj->company_id = Session::get('company_id');
});
}
}
You can extend the BaseModel class on all the models that you want the company_id to be inserted or updated. Take a look at Eloquent Model Events for more information.
The above code will automatically insert or update the company_id to the model that you extend the BaseModel to. When you do a Model::all() or Model::get(), you automatically get the company_id on that Model and you can also perform searches as you requested on Point `
Hope this helps.
well, you can just add the company id to the find query.
Model::where("company_id","=",$company_id):
Or you can create a scope:
class theModel extends Eloquent {
static $company_id;
static for_company($company_id){
self::company_id=$company_id;
return __CLASS__;
}
public function scopeCompany($query)
{
return $query->where('company_id', '=', self::company_id);
}
}
//And later
$scope=theModel::for_company($company_id);
$res=$scope::company->where(...);
Disclaimer: I haven't tried this. Just a solution I constructed. Let me know if this works. This will not work under PHP 5.3

Yii model: Dynamic table relations

Table.linkedIndex is related to LinkedIndex.ID. The value of the field LinkedIndex.TableName is either Linked1 or Linked2 and defines which of these tables is related to a row in Table.
Now i want to make a dynamical link with Yii models so that i can easily get from a Table row to the corresponding Linked1 or Linked2 row:
Table.linkedID = [LinkedIndex.TableName].ID
Example
Table values:
LinkedIndex values:
Now I should get the row from Linked2 where ID=2:
$model = Table::model()->findByPk(0);
$row = $model->linked;
Model
In the model Table, I tried to make the relation to the table with the name of the value of linkedIndex.TableName:
public function relations()
{
return array(
'linkedIndex' => array(self::HAS_ONE, 'LinkedIndex', array('ID' => 'linkedIndex')),
'linked' => array(
self::HAS_ONE,
'linkedIndex.TableName',
array('ID' => 'linkedID'),
)
)
}
But then I get the error:
include(linkedIndex.TableName.php) [function.include]: failed to open stream: No such file or directory
Is there any way to make a dynamic relation Table.linkedID -> [LinkedIndex.TableName].ID with Yii Models?
Per the Yii docs here:
http://www.yiiframework.com/doc/api/1.1/CActiveRecord#relations-detail
I'd suggest using self::HAS_ONE instead (unless there can be multiple rows in LinkedIndex with the same ID - although from the looks of above, I doubt that's the case).
You can link tables together that have different keys by following the schema:
foreign_key => primary_key
In case you need to specify custom PK->FK association you can define it as array('fk'=>'pk'). For composite keys it will be array('fk_c1'=>'pk_с1','fk_c2'=>'pk_c2').
so in your case:
public function relations(){
return array(
'linkedIndex' => array(self::HAS_ONE, 'LinkedIndex', array('ID' => 'linkedIndex')),
);
}
where LinkedIndex is the class name for the LinkedIndex model (relative to your Table model - i.e. same folder. You could change that, of course) and array('ID' => 'linkedIndex') specifies the relationship as LinkedIndex.ID = Table.linkedIndex.
Edit
Looking at your updated example, I think you're misunderstanding how the relations function works. You're getting the error
include(linkedIndex.TableName.php) [function.include]: failed to open stream: No such file or directory
because you're trying to create another relation here:
'linked' => array(
self::BELONGS_TO,
'linkedIndex.TableName',
array('ID' => 'linkedID'),
)
This part: linkedIndex.TableName refers to a new model class linkedIndex.TableName, so Yii attempts to load that class' file linkedIndex.TableName.php and throws an error since it doesn't exist.
I think what you're looking for is to be able to access the value TableName within the table LinkedIndex, correct? If so, that's accessible from within the Table model via:
$this->linkedIndex->TableName
This is made possible by the relation we set up above. $this refers to the Table model, linkedIndex refers to the LinkedIndex relation we made above, and TableName is an attribute of that LinkedIndex model.
Edit 2
Per your comments, it looks like you're trying to make a more complex relationship. I'll be honest that this isn't really the way you should be using linking tables (ideally you should have a linking table between two tables, not a linking table that says which 3rd table to link to) but I'll try and answer your question as best as possible within Yii.
Ideally, this relationship should be made from within the LinkedIndex model, since that's where the relationship lies.
Since you're using the table name as the linking factor, you'll need to create a way to dynamically pass in the table you want to use after the record is found.
You can use the LinkedIndex model's afterFind function to create the secondary link after the model is created within Yii, and instantiate the new linked model there.
Something like this for your LinkedIndex model:
class LinkedIndex extends CActiveRecord{
public $linked;
public static function model($className = __CLASS__){
return parent::model($className);
}
public function tableName(){
return 'LinkedIndex';
}
public function afterFind(){
$this->linked = new Linked($this->TableName);
parent::afterFind();
}
//...etc.
}
The afterFind instantiates a new Linked model, and passes in the table name to use. That allows us to do something like this from within the Linked model:
class Linked extends CActiveRecord{
private $table_name;
public function __construct($table_name){
$this->table_name = $table_name;
}
public static function model($className = __CLASS__){
return parent::model($className);
}
public function tableName(){
return $this->table_name;
}
//...etc.
}
which is how we dynamically create a class with interchangeable table names. Of course, this fails of the classes need to have separate operations done per-method, but you could check what the table_name is and act accordingly (that's pretty janky, but would work).
All of this would result in being to access a property of the linked table via (from within the Table model):
$this->linkedIndex->linked->foo;
Because the value of LinkedIndex.TableName and Table.linkedID is needed to get the values, I moved the afterFind, suggested by M Sost, directly into the Table-Class and changed its content accordingly. No more need for a virtual model.
class Table extends CActiveRecord {
public $linked; // Needs to be public, to be accessible
// ...etc.
public function afterFind() {
$model = new $this->linkedIndex->TableName;
$this->linked = $model::model()->findByPk( $this->linkedID );
parent::afterFind();
}
// ...
}
Now I get the row from Linked2 where ID=2:
$model = Table::model()->findByPk(0);
$row = $model->linked;

Zend_Db_Table Base table or view not found

I have taken over an application written with the use of the Zend MVC and Zend_Db_Table for DB access. I am trying to add a new table but get the error:
Base table or view not found: 1146 Table 'maa_agencies.contact' doesn't exist
However maa_agcencies.contact very much DOES exists and is in the same DB as the rest of the tables being accessed.
Here are my steps and code:
Step 1:
Create the Model Class
file: application/models/DbTable/Contact.php
class Model_DbTable_Contact extends Zend_Db_Table_Abstract
{
protected $_name = 'contact';
}
Step 2:
Instantiate the Class the same way it's done a dozen time in a controller (all other tables work)
file: application/modules/agency/controllers/IndexController.php (also step 3)
$agency_contact = new Model_DbTable_Contact();
Step 3:
Write my data to my new table ($store_contact is an assoc array with key = column name value = value)
$agency_contact->insert($store_contact);
Is there some caching function in Zend I am unaware of?
Some special thing I need to do to tell it I added a new table?
All documentation I have come across says this is all that is required, and as I state above the file I am trying to access my table through is already accessing 2 other tables in the same DB, in fact the line just above where I instantiate my Contact model is this statement that works fine:
$sm = new Model_DbTable_SentEmail();
The name space idea seems awesome! If this system wasn't some bastardization of the framework. Here is a currently working Model
/**
* #category Model_DbTable
* #package Model_DbTable_States
class Model_DbTable_States extends Zend_Db_Table_Abstract
{
protected $_name = 'state_list';
}
Is there some vodoo in the commenting perhaps, I am unable to find anywhere in the code where a namespace is registered at all.
Change your Class names of Model Directory. Add Prefix Application_
Example: Application_Model_DbTable_Contact
You forgot to add the namespace to your class
class Yournamespace_Model_DbTable_Contact extends Zend_Db_Table_Abstract
{
protected $_name = 'contact';
}
IN your application.ini ad this line
autoloaderNamespaces[] = "Yournamespace_"