cakePHP: Why are my model associations not working as a plugin? - model-view-controller

I have a relationship as follows.
Game -> hasMany Highscores
Highscore -> belongsTo Games, Users
When I run the MVC files standalone (within their respective places in the app dir), I get all belongsTo data associated with Highscores. However, when I run the same MVC files as a plugin, within the plugin dir, these associations are lost.
It seems to me that everythig is in order, but to no avail. I am fairly new to cakePHP so I'm sure it's something stupid. I can't for the life figure it out however.
Any help would be greatly appreciated.
I have referenced:
book.cakephp.org/view/117/Plugin-Models
trac.cakephp.org/ticket/3876
aranworld.com/article/143/cakephp-model-associations-from-within-plugin-directories

Are you setting up your relationships using the PluginName as the prefix in the joined Model's name?
That sounds awkward - example
<?php
class MyModel extends AppModel
{
public $name = "MyModel";
public $belongsTo = array(
'User' => array(
'className' => 'SparkPlug.User',
),
);
?>

I ended up using the bindModel method.
$this->Highscore->bindModel(
array('belongsTo' => array(
'User' => array(
'className' => 'SparkPlug.User'
)
)
)
);
Not ideal and still unsure why my relationships/associations are getting lost. But this will have to do.

Related

how to use Laravel Rinvex Attributes?

I'm trying to use https://github.com/rinvex/attributes, and can't understand how.
Docs are not clear for me and i need help.
After installing the package i've done next:
I have \App\Models\Product class that i want to make attributable.
So I put in model
use Rinvex\Attributes\Traits\Attributable;
class Product extends Model
{
use CrudTrait;
use Sluggable;
use Attributable;
/***/
In AppServiceProvider's boot():
app('rinvex.attributes.entities')->push(App\Models\Product::class);
Next - just like in docs - creating the attribute in Tinker console just like that:
app('rinvex.attributes.attribute')->create([
'slug' => 'size',
'type' => 'varchar',
'name' => 'Product Size',
'entities' => ['App\Models\Product'],
]);
In DB i see added entries in attributes_entries and attributes tables.
But when i try to call
$product->size = 50;
$product->save(); - got "not found field in Model".
What do i do wrong?
Did you register varchar type? As it mentioned in documentation,
Rinvex Attributes does NOT register any types by default (see https://github.com/rinvex/laravel-attributes#register-your-types)
So i suggest you to add this code in your service providers register method:
Attribute::typeMap([
'varchar' => \Rinvex\Attributes\Models\Type\Varchar::class,
]);
Don't forget to include this class
use Rinvex\Attributes\Models\Attribute

yii find models through related models by using having

For example I have two related models with MANY_MANY relation.
Need to find all models which name contains 'test' or in which relation model2.name contains 'test'.
On sql I wrote this query and it's what I want to get from ActiveRecord in result by using standard relations mechanism and CDbCriteria.
SELECT
m1.*
FROM
model1 m1
LEFT JOIN model_model mm
ON mm.from_id = m1.id
LEFT JOIN model2 m2
ON mm.to_id = m2.id
GROUP BY m1.id
HAVING (
m1.name LIKE '%test%'
OR GROUP_CONCAT(m2.name) LIKE '%test%'
);
Simple use Activerecord.findBySql is not good solution because I have many models such as above. So for faster combination any models a relations is prefered.
When I use CDbCriteria.with Yii generate 2 query.
When I use CDbCriteria.with with CDbCriteria.together Yii tried to select all columns from related tables, it's redundantly and may be slowly in future because number of relations can become much more than in this example.
Have any idea?
Thanks.
You should define the relation in "M1" model class:
public function relations()
{
return array(
'M2s' => array(self::MANY_MANY, 'M2',
'model_model(from_id, to_id)'),
);
}
In your M2 model create a scope:
public function nameScope($name)
{
$this->getDbCriteria()->mergeWith(array(
'condition'=>'name LIKE :name',
'params'=>array(':name'=>"%{$name}%"),
));
return $this;
}
If your ready you can do this:
M1::model()->findAll(
array(
'condition' => 'name LIKE %test%',
'with' => array(
'M2s' => array(
'scopes' => array(
'nameScope' => 'test',
)
)
),
)
);

Laravel: Eloquent how to update a model and related models in one go

Does anyone know if it is possitble to do the folowing:
Let's say we have a model called User and a model calledd BestFriend. The relation between the User and the best friend is 1:1.
I would like for these cases be able to do something like this, change my city and the city of my friend at the same time.
$me = User::find(1);
$me->update(array(
'city' => 'amsterdam',
'bestfriend.city' => 'amsterdam'
));
So basically I would like to know if Eloquent is smart enough to understand the relationship based on the array key 'bestfriend.city'.
Thanks in advance for any help!
Update:
Found the solution on the Laravel forums but im posting it here as well if someone else is looking for the same thing :)
In the model you add
// In your model...
public function setBestFriendArrayAttribute($values)
{
$this->bestfriend->update($values);
}
And then you can call it like this
$me->update(array(
'city' => 'amsterdam',
'BestFriendArray' => array(
'city' => 'amsterdam'
)
));
Works like a charm!
You don't need to set it on your model. You can do it on your controller like this.
$me = User::find(1)->bestFriend()->update(array(
'city' => 'amsterdam',
'bestfriend.city' => 'amsterdam'
));
I just modified your update a little bit.
Eloquent is pretty smart, but I don't believe it can do that. You would have to update User and BestFriend independently. But once you've done that, Eloquent does have methods for attaching the two.
$me = User::find(1);
$bff= BestFriend::find(1);
$me->city = 'amsterdam';
$bff->city = 'amsterdam';
$me->bestfriend()->associate($bff);
This is of course assuming your User model has a function that looks like...
public function bestfriend()
{
return $this->hasOne('BestFriend');
}
If you want to save same city name to both entities this will do the job:
$me = User::find(1);
$me->update(array(
'city' => 'amsterdam',
));
And in your model:
public function setCityAttribute($value)
{
$this->attributes['city'] = $value;
$this->bestfriend->city= $value;
$this->bestfriend->save();
}

Laravel Seeding Does not Fill in Fields

I have a database seed file:
class ContactTableSeeder extends Seeder {
public function run()
{
$contacts = array(
array(
'first_name' => 'Test',
'last_name' => 'Contact',
'email' => 'test.contact#emai.com',
'telephone_number' => '0111345685',
'address' => 'Address',
'city' => 'City',
'postcode' => 'postcode',
'position' => 'Director',
'account_id' => 1
)
);
foreach ($contacts as $contact) {
Contact::create($contact);
}
}
}
When I run php artisan migrate:refresh --seed it seeds the database and creates the relevant record in the contacts table, except that it does not fill the fields with any of the information in the seed array. I am using the exact same syntax for other tables and they work fine, and I've also checked each field thoroughly to make sure they match the database fields but no matter what I do it will not seed correctly.
Does anyone have any ideas?
I had this same problem but none of the above solutions worked for me. It turned out to be due to having a construct function in my model! After I removed this it worked fine!
public function __construct()
{
parent::__construct();
}
EDIT:
After further reading on this I discovered the issue is due to the fact that if you are going to include a constructor in your model must accept the attributes parameter and pass it to the parent. If you do this then the constructor does not break the DB seeding (and probably other things). I hope this saves someone else a headache.
public function __construct($attributes = array())
{
parent::__construct($attributes);
}
Turns out the issue was to do with relationships in my models.
For future visitors to this question: make sure to check all the functions in your models that define hasOne/hasMany/etc relationships. Read though the Eloquent docs for more.
Do you have $this->call("ContactTableSeeder") in your DatabaseSeeder class' run() function?
If you have ContactTableSeeder in it's own file, is the file named ContactTableSeeder.php exactly? If not it would fail to load according to the PSR-0 Standard.
These are my first thoughts.
Have you tried to replace the following lines:
foreach ($contacts as $contact) {
Contact::create($contact);
}
with
DB::table('contact')->insert($contacts);
assuming your table name is contact.
And also, make sure you have line like this
$this->call('ContactTableSeeder');
in your DatabaseSeeder class.

How to setup has and belongs to many (HABTM) association between two models?

I am new to cake and I am facing one problem related with association.
I am having three tables: users, messages and messages_users and I am using HABTM relation for this in message model as:
var $hasAndBelongsToMany = array(
'Users' => array (
'className' => 'User',
'join_table' => 'messages_users',
'foreignKey' => 'message_id',
'associationForeignKey' => 'reciever_id',
'conditions'=> array('MessagesUser.reciever_id' => '$this->Session->read("Id")')
)
);
My problem is when any user will login,he must be able to see the list of messages he got along with the senders name in the table.
But for me this relation is fetching only messages_users data,
My controller is like this,
<?php
class MessagesController extends AppController {
var $name = 'Messages';
//var $scaffold;
function home($id = null)
{
//$this->Message->id=$id;
//$messages_users = $this->Message->MessagesUser->find('all',array('conditions'=>array('MessagesUser.reciever_id'=>$this->Session->read("Id"))));
$messages_users = $this->Message->MessagesUser->find('all',array('fields'=>array('id','name')));
// $this->set(compact('tags'));
print_r($messages_users);
$this->set('messages_users',$messages_users);
$i=0;
foreach ($messages_users as $messages_user):
$new = $messages_users[$i]['MessagesUser']['sender_id'];
$i++;
print_r($new);
$messages = $this->Message->Users->find('all',array('conditions'=>array('Users.id'=>$new)));
// print_r($messages);
$this->set('messages',$messages);
endforeach;
}
} ?>
So please anybody help me how to get the result for this.
From the CookBook:
Remember that associations are defined
'one way'. If you define User hasMany
Recipe that has no effect on the
Recipe Model. You need to define
Recipe belongsTo User to be able to
access the User model from your Recipe
model
Have you setup the relationship in your users model to your messages model?
Setting it up like you have you'll be able to access users from the messages model but not messages from the user model.
Reference The CookBook Models section on Has And Belongs To Many for more details.

Resources