Nesting of CActiveRecord - activerecord

class SomeModel extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{some_table}}';
}
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return self::model()->findAll($criteria);
}
}
This method works properly when I call it from controller
SomeModel::model()->getItemByParentId($someVariable)
But now I have 3 very similar to SomeModel models, so I want to put common methods to one class
class CommonModel extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return self::model()->findAll($criteria);
}
}
class FirstModel extends CommonModel
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{first_table}}';
}
}
class SecondModel extends CommonModel
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{second_table}}';
}
}
But get error
The table "CommonModel" for active record class "CommonModel" cannot
be found in the database.
What is wrong?

Try to change:
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return static::model()->findAll($criteria);
}

Related

laravel relationship between 5 tables

I have 5 tables User, Profile, Address,State,City .Need to create relationship between tables.Address has State id , City id and Profile id in the table.Profile has User Id in the table.City has State Id in the table. How to write relationship between table
class City extends Model
{
public function state() {
return $this->belongsTo('App\State');
}
public function addresses() {
return $this->hasMany('App\Address');
}
}
class State extends Model
{
public function cities() {
return $this->hasMany('App\City');
}
public function addresses() {
return $this->hasMany('App\Address');
}
}
class Profile extends Model
{
public function address() {
return $this->belongsTo('App\Address');
}
public function user() {
return $this->belongsTo('App\User');
}
}
class Address extends Model
{
public function profile() {
return $this->belongsTo('App\Profile');
}
public function city() {
return $this->belongsTo('App\City');
}
public function state() {
return $this->belongsTo('App\State');
}
}
// users table
public function profile(){
return $this->hasOne('App\Profile');
}
Generally your model design is true, i have edited a few parts. Try the codes below.
class City extends Model
{
public function state()
{
return $this->belongsTo('App\State');
}
public function addresses()
{
return $this->hasMany('App\Address');
}
}
class State extends Model
{
public function cities()
{
return $this->hasMany('App\City');
}
public function addresses()
{
return $this->hasMany('App\Address');
}
}
class Profile extends Model
{
public function addresses()
{
return $this->hasMany('App\Address');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
class Address extends Model
{
public function profile()
{
return $this->belongsTo('App\Profile');
}
public function city()
{
return $this->belongsTo('App\City');
}
public function state()
{
return $this->belongsTo('App\State');
}
}
class User extends Model
{
public function profile()
{
return $this->hasOne('App\Profile');
}
}
By the way, Laravel relationships add default keys according to your method names. If you have problem about it you can find info from official documents. For example:
$this->belongsTo('App\Model', 'foreign_key', 'other_key');
as #mustafa.akcoban says...
When you use belongsTo Eloquent will work as follow
$this->belongsTo('App\City', 'foreign_key', 'other_key');
// foreign_key = is the primary key in the related model, by default 'id' for Eloquent
// other_key = is the field in the current model that contains the id of the other model, by default othermodelname_id for Eloquent
// For eg. 'App\City', 'id', 'city_id'
When you use hasMany Eloquent works as follow
$this->hasMany('App\Model', 'currentmodel_id', 'primary_key');
// currentmodel_id = is the field that contains the current model primary key in the related model
// primary_key = is the current primary key model that will be in the other model, by default id for Eloquent
// For eg. 'App\City', 'state_id', 'id'
Remember you can or can't use second and third parameter, if something is wrong Laravel dump will tell you what column was not found in the table, and you will can fix.
Please try and practice this, and let me know how it works :)

How in laravel to make a deep HasManyThrough?

I created a relationship like this:
Type.City.Street.House.Apartment
In this relation, the apartment must depend on the House and on the Type at the same time, so result sql query must be like this:
select * from `apartments` where `apartments`.`house_id` in ('1', '2', '3') and `type_id` = '777'
The problem is that the HasManyThrough relationship only looks at a two of levels and it's not possible to get to the very first model with it.
Please, advise how this can be done?
My models definations:
class Type extends Model {
public function city() {
return $this->hasMany('App\City');
}
}
class City extends Model {
public function street() {
return $this->hasMany('App\Street');
}
}
class Street extends Model {
public function house() {
return $this->hasMany('App\House');
}
}
class House extends Model {
public function Apartment() {
return $this->hasMany('App\Apartment');
//->where('type_id', '=' type.id) ?????
}
}
class Apartment extends Model {
public $fillable = ['house_id', 'type_id']
}
I would add a mapping for house_id in Apartment model and sets bidirectional mappings among your models
class Apartment extends Model {
public $fillable = ['house_id', 'type_id'];
public function house() {
return $this->belongsTo('App\House', 'house_id');
}
}
class Type extends Model {
public function city() {
return $this->hasMany('App\City');
}
}
class City extends Model {
public function type() {
return $this->belongsTo('App\Type', 'type_id');
}
public function street() {
return $this->hasMany('App\Street');
}
}
class Street extends Model {
public function city() {
return $this->belongsTo('App\City', 'city_id');
}
public function house() {
return $this->hasMany('App\House');
}
}
class House extends Model {
public function street() {
return $this->belongsTo('App\Street', 'street_id');
}
public function Apartment() {
return $this->hasMany('App\Apartment');
//->where('type_id', '=' type.id) ?????
}
}
then you can query apartments as per your criteria like
Apartments::whereHas('house.street.city.type', function ($query) use ($type_id) {
$query->where('id', '=', $type_id);
})
->whereHas('house', function ($query) use ($house_ids) {
$query->whereIn('id', $house_ids);
});
And i guess there is no need for type_id in Apartments model
I created a HasManyThrough relationship with unlimited levels: Repository on GitHub
After the installation, you can use it like this:
class Type extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function Apartment() {
return $this->hasManyDeep(Apartment::class, [City::class, Street::class, House::class])
->where('apartments.type_id', $this->id);
}
}
Unfortunately, this doesn't work with eager loading.

how can I show this combination with select?

models structure it looks like the following
class Attribute extends Model
{
public function products()
{
return $this->belongsToMany(Product::class);
}
public function attribute_options()
{
return $this->hasMany(AttributeOption::class);
}
}
class AttributeOption extends Model
{
public function attribute_option()
{
return $this->hasMany(CombinationDetail::class);
}
public function attribute(){
return $this->belongsTo(Attribute::class);
}
}
class Combination extends Model
{
public function combination_details()
{
return $this->hasMany(CombinationDetail::class);
}
}
class CombinationDetail extends Model
{
protected $fillable = ['attribute_options_id'];
public function attribute_options()
{
return $this->belongsTo(AttributeOption::class);
}
}
Relationship models like this.
combination table
combination_details table
how can i show this with selectbox or div with javascript

Laravel - check if the Eloquent object is found inside model

In my controller I would like to have this:
class TodoController extends Controller {
public function getDone($todoId)
{
Todo::find($todoId)->markAsDone();
}
}
model I have:
class Todo extends Eloquent {
public function markAsDone()
{
if (???) {
$this->is_done = 1;
$this->save();
}
}
}
How can I check if the model is found and is present in $this?
In your case, checking the existence of ToDo object can only be done in controller. Because in your current code Todo::find($todoId)->markAsDone(); if the $todoId is invalid, you will be have BIG error, trying to get property of non-object. So its better to do this.
class TodoController extends Controller {
public function getDone($todoId)
{
$todo = Todo::find($todoId);
if ($todo) {
$todo->markAsDone();
}
}
}
And in your model
class Todo extends Eloquent {
public function markAsDone()
{
$this->is_done = 1;
$this->save();
}
}

How add a specific variable in custom AuthStorage in Zend Framework 2

I'm working on ZF2 and I have developped my own storage for authentication but I wonder how to add a new persistent variable (session-like).
Look My Auth Storage :
<?php
namespace Application\Model;
use Zend\Authentication\Storage;
use Zend\Authentication\Storage\StorageInterface;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
use Application\Model\User;
class MyAuthStorage implements Storage\StorageInterface, ServiceManagerAwareInterface
{
protected $storage;
protected $userTable;
protected $resolvedIdentity;
protected $serviceManager;
public function isEmpty() {
[...]
}
public function read() {
[...]
}
public function write($contents) {
[...]
}
public function clear() {
[...]
}
public function getStorage() {
[...]
}
public function setStorage(Storage\StorageInterface $storage) {
[...]
}
public function getUserTable() {
[...]
}
public function getServiceManager() {
[...]
}
public function setServiceManager(ServiceManager $serviceManager) {
[...]
}
}
I would like to add a variable called foo in my storage (my session ?)
I try this, but it doesn't work :
protected $foo;
public function setFoo($value) {
$this->foo= $value;
}
public function getFoo() {
return $this->foo;
}
Any ideas ?
Ok, I found something and it works for me :
I've added these things in my auth storage class
use Zend\Session\Container;
Then,
protected $container;
public function setContainer(Container $container) {
$this->container = $container;
return $this->container;
}
public function getContainer() {
if (!isset($this->container)) {
$this->setContainer(new Container('myauthstorage'));
}
return $this->container;
}
And now I can do in my controller stuff like that :
$container = $this->getServiceLocator()->get('AuthService')->getStorage()->getContainer();
$container->foo = true;
if ($container->foo) {
// Congrats !
}
A good example how to write last login time.
namespace Application\Model;
use Zend\Authentication\Storage;
class AuthStorage extends Storage\Session
{
public function setRememberMe($rememberMe = 0, $time = 1209600)
{
if ($rememberMe == 1) {
$this->session->getManager()->rememberMe($time);
}
}
public function forgetMe()
{
$this->session->getManager()->forgetMe();
}
public function lastLogin()
{
$this->session->{$this->getMember()}->last_login = time();
}
}
Check this tutorial :
http://samsonasik.wordpress.com/2012/10/23/zend-framework-2-create-login-authentication-using-authenticationservice-with-rememberme/
Sounds like your personnal AuthStorage should extends Storage\Session like this :
namespace SanAuth\Model;
use Zend\Authentication\Storage;
class MyAuthStorage extends Storage\Session
{
public function setRememberMe($rememberMe = 0, $time = 1209600)
{
if ($rememberMe == 1) {
$this->session->getManager()->rememberMe($time);
}
}
public function forgetMe()
{
$this->session->getManager()->forgetMe();
}
}

Resources