CakePHP belongsTo not working - mysql

I have a couple of tables in my database:
CREATE TABLE IF NOT EXISTS `team_players` (
`artificialid` int(11) NOT NULL AUTO_INCREMENT,
`team_name_id` int(11) NOT NULL,
`player_id` int(11) NOT NULL,
PRIMARY KEY (`artificialid`)
)
And:
CREATE TABLE IF NOT EXISTS `team_names` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL
)
And I have set up my TeamPlayer model like this:
class TeamPlayerModel extends AppModel {
public $belongsTo = array(
'TeamName',
'Player'
)
);
}
The players table has a field id, but neither of the associations are working.
I don't really understand why it isn't working, I have something like this working in another app, pretty much line for line.
Thanks in advance, I really appreciate any help.

You can try to setup your model:
TeamPlayer.php:
class TeamPlayer extends AppModel {
public $hasMany = array(
'PlayerName'
)
) ;
}
TeamName.php:
class TeamName extends AppModel {
public $belognsTo = array(
'TeamPlayer'
)
) ;
}

Related

Relationships of models (Laravel 5.2)

My tables (Mysql DB):
// Stores Table
CREATE TABLE IF NOT EXISTS `app_beta`.`stores` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`))
// Items Table
CREATE TABLE IF NOT EXISTS `app_beta`.`items` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`title` TEXT NOT NULL,
`content` LONGTEXT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_items_user_id`
FOREIGN KEY (`user_id`)
REFERENCES `app_beta`.`users` (`id`))
// Products Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products` (
`id` INT UNSIGNED NOT NULL,
`reviews` DECIMAL(7,1) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_products_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
// Product_Store Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products_stores` (
`product_id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NOT NULL,
`url` VARCHAR(255) NOT NULL,
CONSTRAINT `fk_products_store_product_id`
FOREIGN KEY (`product_id`)
REFERENCES `app_beta`.`products` (`id`),
CONSTRAINT `fk_products_stores_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`))
// Offers Table
CREATE TABLE IF NOT EXISTS `app_beta`.`offers` (
`id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NULL,
`url` VARCHAR(255) NOT NULL,
`start_date` DATE NOT NULL,
`end_date` DATE NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_offers_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`),
CONSTRAINT `fk_offers_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
Add. Info:
My tables are migrated. Just to clarify... the products and offers inherit from the items table. If the item is not created I can not add products and offers.
The product can have the title, summary, content, category etc... same for the offer.
The product can be on 1-many stores
The offer can be only on 1-1 store.
If I'm wrong LET ME KNOW!
** Please, I want someone to help me creating the relationships between the Item model, product and offer. Can i use polymorphic relations? **
Models DONE:
class Store extends Model
{
public function offers()
{
return $this->hasMany('App\Offer');
}
public function products()
{
return $this->hasMany('App\Product');
}
}
class Product extends Model
{
public function stores()
{
return $this->belongsToMany('App\Store');
}
}
class Offer extends Model
{
public function store()
{
return $this->belongsTo('App\Offer');
}
}
using php artisan tinker, all works nice!
namespace App
$user = new User
$store = new Store
$item = new Item
$item->id = 1
$item->user_id = 1
$item->title = 'test'
$item->content 'test'
$item->save();
true
$item2 = new Item
$item2->id = 2
....
true
$product1 = new Product
$product1->id = 1 (FK item->id)
$product1->reviews = 5
$product1->save()
true
$offer1 = new Offer
$offer1->id = 2 (FK item->id)
$offer1->store_id = 1
...
true
I'll add later a function to attach product to one or many stores (products_stores table).
Thanks.
This is how I think you can have a good start...
First of all, your model and migration can handle all it.
There is for relationship:Laravel 5.2 Relationship
There is for migration:Laravel 5.2 Migration
So there you create your migration:
Schema::create('stores', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->string('name', 50);
$table->timestamps();
});
Schema::create('items', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->text('title');
$table->longText('content');
$table->timestamps();
});
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->decimal('reviews', 7,1);
$table->timestamps();
});
Schema::create('offers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->bigInteger('item_id')->unsigned();
$table->foreign('item_id')->references('id')->on('items');
$table->decimal('price', 7,2);
$table->string('url', 255);
$table->dte('start_date');
$table->dte('end_date');
$table->timestamps();
});
So, once you did this, you can make your relationship onto your model. This way you don't need all the "between" tables. When you will use associate(), Laravel will create the link for you. This way you can do something like this: $offer->store()->name to get the name of the store of the current offer. Take a look:
Into Store's model
public function products()
{
return $this->hasMany(Product::class);
}
public function offers()
{
return $this->hasMany(Offer::class);
}
Into Offer's model
public function store()
{
return $this->belongsTo(Store::class);
}
This way, You create a one-to-many relation. Has I said, $offer->store() will retrieve the store of the offer. $store->offers()->get() will retrieve all offer of the store.
Hope it help.
EDIT
There is one only problem with what I said. The n + 1 problem. So like it explain there(search google "laravel n+1 problem" and pick the link to laracast) (can't put it as a link, not enough reputation) , when you call things like I said, the script will do 2 query. When you use a foreach() loop, it'll have as much loop +1 query. I suggest you to do things like that
$offers = Offer::with('store')->all();
This way you'ill have only 1 query and you will still able to do
$offer->store;
without doing another query.
When you use $model = Model::with('something')->all();, the query will fetch data from 2 table and return the result with an array into an array. Like this:
offers {
[0]:{a,b,c,d,e, store{a,b,c,d,e}}
[1]:{a,b,c,d,e, store{a,b,c,d,e}}
[2]:{a,b,c,d,e, store{a,b,c,d,e}}
[3]:{a,b,c,d,e, store{a,b,c,d,e}}
}
You can use the opposite:
$stores = Store::with('offers')->all();
So you can use:
$store->offers[i]->somthing;
Because the array will look like this:
stores {
[0]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[1]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[2]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
}

Cakephp $scaffold doesn't display associated models

Help me please, I'm desperate!
I have this schema:
CREATE TABLE `baskets` (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`name` varchar(20)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `apples` (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`basket_id` INT UNSIGNED ,`type` int,
FOREIGN KEY (basket_id) references baskets(id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
These are my models:
class Apple extends AppModel {
public $name = 'Apple';
public $recursive = 2;
public $belongsTo = 'Basket';
}
class Basket extends AppModel {
public $name = 'Basket';
public $recursive = 2;
public $hasMany = 'Apple';
}
However, when I call the variable $scaffold on either one of them, and try to update or create a new apple; the little drop-down thingy where I would normally choose a basket is empty.
What can I do???? I'm gonna get fired if I don't solve this by monday :(

How to find all objects using CakePHP model associations?

Here's my database schema:
create table Personas
(
id int primary key AUTO_INCREMENT,
Nombre varchar(255),
Apellidos varchar(255),
FechaDeNacimiento date,
Sexo Bool,
CarnetDeIdentidad varchar(255)
);
create table Tutors
(
id int primary key AUTO_INCREMENT,
persona_id int,
FOREIGN KEY (persona_id) REFERENCES Personas(id)
);
create table Alumnos
(
id int primary key AUTO_INCREMENT,
persona_id int,
FOREIGN KEY (persona_id) REFERENCES Personas(id)
);
create table CoordinadorDeProgramas
(
id int primary key AUTO_INCREMENT,
persona_id int,
FOREIGN KEY (persona_id) REFERENCES Personas(id)
);
And here are my Model declarations:
<?php
class Alumno extends AppModel {
public $belongsTo = 'Persona';
}
<?php
class Coordinadordeprograma extends AppModel {
public $belongsTo = 'Persona';
}
<?php
class Tutor extends AppModel {
public $belongsTo = 'Persona';
}
<?php
class Persona extends AppModel {
public $hasOne = array('Alumno', 'Tutor', 'Coordinadordeprograma');
}
In my Controller I just want to fetch all Persona records if they have a foreign key relationship in Alumnos (for example).
Here's my code, I hope it illustrates what I'm trying to do:
public function filter($type = null) {
if ($type == "alumno") { // www.app.com/personas/filter/alumno
$this->set('personas', $this->Alumno->Persona->find('all'));
}
}
However this is returning every single Persona record, and not just the ones that have a record in the Alumno table.
How do you suggest I solve this problem? I thought that by using $this->Alumno->Persona I would only be reaching for Persona's that are in the Alumno table.
Thanks!
You could use the containable behaviour and just make a find on Alumno??
$this->set('personas', $this->Alumno->find('all'));
it should retrieve the 'Alumno' with all the models associated to it. You could also choose which models you want to retrieve. For example, this code will retrieve all the 'Alumno' with its corresponding 'Persona'
$this->set('personas', $this->Alumno->find('all',array('contain'=>array('Persona')));
An of course.. like #Paulo answered, you could manually make the join, but using "containable" is cleaner. I only make the join manually when I don't have any other solution.
Hope this helps,
You can try make INNER JOIN on the fly, like this:
$personas = $this->Alumno->Persona->find('all', array(
'joins' => array(
array(
'table' => 'Alumnos',
'alias' => 'Alumno',
'type' => 'INNER',
'conditions' => 'Persona.id = Alumno.persona_id'
)
)
));
$this->set('personas', $personas);

cakephp messaging system scheme/model/controller Best Practice?

I am trying to implement a simple messaging system for my users.
I am not an habtm expert, so any assistance will be appreciated!
Here is what I got this far, please make any suggestions!! (cake1.3)
CREATE TABLE IF NOT EXISTS `app_messages` (
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`from_user_id` int(8) unsigned DEFAULT NULL,
`title` varchar(255) DEFAULT NULL,
`body` text,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `app_messages_users` (
`id` int(8) unsigned NOT NULL,
`message_id` int(8) unsigned NOT NULL,
`to_user_id` int(8) unsigned NOT NULL,
`read` tinyint(1) DEFAULT '0',
`replied` tinyint(1) NOT NULL DEFAULT '0',
`trash` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
);
Message.php
var $hasAndBelongsToMany = array(
'User' =>
array(
'className' => 'User',
'joinTable' => 'messages_users',
'foreignKey' => 'message_id',
'associationForeignKey' => 'to_user_id',
'unique' => true
)
);
User.php
var $hasMany = array(
'Message' => array(
'className' => 'message',
'foreignKey' => 'from_user_id',
'dependent' => true
)
So now, my question is, Am I doing this correct?
How do I go around creating a SEND MESSAGE function, to insert correct values to both tables?
I am a total noob regarding HABTM relationships, but I am trying to learn. Have spent several hours reading about it on the web, but still, need to ask if I am going the right way.
Thanks for your time!!
-Tom
Given that your join table has additional fields (read, replied, trash), you should not use an HABTM relationship. If you do, you won't be able to access them from your application. So instead, you should configure two hasMany associations through a new model for the join table. It is well explained here in the CookBook.
So you'll end up having something like this:
// User.php
class User extends AppModel {
public $hasMany = array(
'MessageUser' /* you can call this 'SentMessage' or something that makes more sense */
);
}
// Message.php
class Message extends AppModel {
public $hasMany = array(
'MessageUser'
);
}
// MessageUser.php
class MessageUser extends AppModel {
public $belongsTo = array(
'User', 'Message'
);
}

Is this possible to join tables in doctrine ORM without using relations?

Suppose there are two tables.
Table X--
Columns:
id x_value
Table Y--
Columns:
id x_id y_value
Now I dont want to define relationship in doctrine classes and i want to retrieve some records using these two tables using a query like this:
Select x_value from x, y where y.id="variable_z" and x.id=y.x_id;
I m not able to figure out how to write query like this in doctrine orm
EDIT:
Table structures:
Table 1:
CREATE TABLE IF NOT EXISTS `image` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`random_name` varchar(255) NOT NULL,
`user_id` int(11) NOT NULL,
`community_id` int(11) NOT NULL,
`published` varchar(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=259 ;
Table 2:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`city` varchar(20) DEFAULT NULL,
`state` varchar(20) DEFAULT NULL,
`school` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=20 ;
Query I am using:
$q = new Doctrine_RawSql();
$q ->select('{u.*}, {img.*}')
->from('users u LEFT JOIN image img ON u.id = img.user_id')
->addComponent('u', 'Users u')
->addComponent('img', 'u.Image img')
->where("img.community_id='$community_id' AND img.published='y' AND u.state='$state' AND u.city='$city
->orderBy('img.id DESC')
->limit($count+12)
->execute();
Error I am getting:
Fatal error: Uncaught exception 'Doctrine_Exception' with message 'Couldn't find class
u' in C:\xampp\htdocs\fanyer\doctrine\lib\Doctrine\Table.php:290 Stack trace: #0
C:\xampp\htdocs\fanyer\doctrine\lib\Doctrine\Table.php(240): Doctrine_Table- >initDefinition() #1 C:\xampp\htdocs\fanyer\doctrine\lib\Doctrine\Connection.php(1127):
Doctrine_Table->__construct('u', Object(Doctrine_Connection_Mysql), true) #2
C:\xampp\htdocs\fanyer\doctrine\lib\Doctrine\RawSql.php(425): Doctrine_Connection-
>getTable('u') #3 C:\xampp\htdocs\fanyer\doctrine\models\Image.php(33): Doctrine_RawSql-
>addComponent('img', 'u.Image imga') #4 C:\xampp\htdocs\fanyer\community_images.php(31):
Image->get_community_images_gallery_filter(4, 0, 'AL', 'ALBERTVILLE') #5 {main} thrown in
C:\xampp\htdocs\fanyer\doctrine\lib\Doctrine\Table.php on line 290
Try something like this:---
$q = new Doctrine_RawSql();
$this->related_objects = $q->
select('{o.name}')->
from('tagset t1 JOIN tagset t2 ON t1.tag_id = t2.tag_id AND t1.object_id != t2.object_id JOIN object o ON t2.object_id = o.id')->
addComponent('o','Object o')->
where('t1.object_id = ?', $this->object->id)->
groupBy('t2.object_id')->
orderBy('COUNT(*) DESC')->
execute();
You can write the sql directly to the db driver.You won't get back any hydrated arrays or objects however. But it does come in handy sometimes:
$sql = "SELECT * FROM... ";
$pdo = Doctrine_Manager::connection()->getDbh();
$data = $pdo->query($sql)->fetchAll();
You can manually alter your Table Class in Symfony 1.4 but this should be done carefully, because you are not linking tables on Database level which normally should happen.
class TableName extends BaseTableName
{
public function setUp()
{
$this->hasOne('LinkedTableName', array(
'local' => 'link_id',
'foreign' => 'link_id'));
parent::setUp();
}
}
Possible duplicate: doctrine join without relation