How to refer filling of one form with the filling of other in Atk4 - atk4

I have made two forms for logged users. The first one is for trip info (name, short description) and the second is for different landmarks (name, description) that are part of the trip of current user. Is it possible to "connect" the user with filling of trip form and the form for landmarks that is going to be used several times for different landmarks. I have the models "trips", "user" and "landmarks" with respective id's, but I can not solve the problem alone.
........................
I have tried this and it happened (thanks to Romaninsh):
function page_trips(){
$this->api->stickyGET('id');
$id=$this->api->auth->get('id');
$f=$this->add('Form');
$f->addField('line','name')->setNotNULL();
$f->addField('Text','short_desc')->setNotNULL();
$f->setSource('trips');
$f->setConditionFromGET();
$f->dq
->set('user_id',$id);
$f->addSubmit('Next');
if($f->isSubmitted())
{
$f->update();
$f->js()->univ()->location($this->api->getDestinationUrl('../targets')
)
->execute();
}
}
Now I can enter an info about new trip and save to table with respective user id. The rest of the task is to add different landmarks to current trip.

Not sure if it's what you are looking as i used a two page design and you would probably use another one to add/edit/delete landmarks but maybe this will give you some ideas.
I created a three tables in the database - trip, landmark and landmarktrip with the following definitions.
CREATE TABLE IF NOT EXISTS `landmark` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET latin1 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=6 ;
INSERT INTO `landmark` (`id`, `name`) VALUES
(1, 'Xintiandi'),
(2, 'Pearl TV Tower'),
(3, 'YuYuan Gardens'),
(4, 'Shanghai Botanical Gardens'),
(5, 'Shanghai World Financial Centre');
CREATE TABLE IF NOT EXISTS `landmarktrip` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trip_id` int(10) NOT NULL,
`landmark_id` int(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=7 ;
INSERT INTO `landmarktrip` (`id`, `trip_id`, `landmark_id`) VALUES
(1, 1, 1),
(2, 1, 2),
(3, 1, 3),
(4, 2, 3),
(5, 2, 4),
(6, 1, 5);
CREATE TABLE IF NOT EXISTS `trip` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(10) NOT NULL,
`name` varchar(255) COLLATE utf8_bin NOT NULL,
`short_desc` varchar(255) COLLATE utf8_bin NOT NULL,
`start_date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='7741244' AUTO_INCREMENT=3 ;
INSERT INTO `trip` (`id`, `user_id`, `name`, `short_desc`, `start_date`) VALUES
(1, 1, 'Shanghai 1', 'First Trip To China', '2011-10-13'),
(2, 1, 'Shanghai 2', 'Return Visit', '2011-10-21');
And then created models in wwwroot/website/lib/Model as follows
Landmark.php
class Model_Landmark extends Model_Table {
public $entity_code='landmark';
public $table_alias='l';
function init(){
parent::init();
$this->addField('id')->mandatory(true)->system(true)->visible(false);
$this->addField('name')->mandatory(true);
}
}
Trip.php
class Model_Trip extends Model_Table {
public $entity_code='trip';
public $table_alias='t';
function init(){
parent::init();
$this->addField('id')->mandatory(true)->system(true)->visible(false);
$this->addField('user_id')->defaultValue($this->api->auth->get('id'))->visible(false);
$this->addField('name')->mandatory(true);
$this->addField('short_desc')->mandatory(true);
$this->addField('start_date')->dataType('date')->mandatory(true);
}
}
}
LandmarkTrip.php
class Model_LandmarkTrip extends Model_Table {
public $entity_code='landmarktrip';
public $table_alias='lt';
function init(){
parent::init();
$this->addField('id')->system(true)->visible(false);
$this->addField('trip_id')->refModel('Model_Trip')->mandatory(true);
$this->addField('landmark_id')->refModel('Model_Landmark')->mandatory(true);
}
}
Created two pages in wwwroot/website/page, one to add the trips and one for the itinerary as i dont see how with the form approach you are using, you can select which trip you want to see the details of.
trips.php
class page_trips extends page {
function init() {
parent::init();
$p=$this;
$c=$p->add('CRUD')->setModel('Trip');
$c->setMasterField('user_id', $this->api->auth->get('id'));
}
}
itinerary.php
class page_itinerary extends page {
function init() {
parent::init();
$p=$this;
$this->js()->_load('trip_univ');
$triplist=$this->api->db->dsql()->table('trip t')
->field('t.id')
->field('t.name')
->where('t.user_id', $p->api->auth->get('id'))
->order('t.start_date')
->do_getAssoc();
if ($_GET['trip']){
$curr_trip=$_GET['trip'];
} else {
$earliest=$this->api->db->dsql()->table('trip')
->field('min(start_date)')
->where('user_id',$this->api->auth->get('id'))
->do_getOne();
$curr_trip=$this->api->db->dsql()->table('trip')
->field('id')
->where('user_id',$this->api->auth->get('id'))
->where('start_date',$earliest)
->do_getOne();
}
$f=$p->add('Form')->setFormClass('horizontal');
$list=$f->addField('dropdown','trip')->setValueList($triplist)->set($curr_trip);
$list->js('change')->univ()->viewTrip($p->api->getDestinationURL(null), $list);
$lt=$p->add('CRUD')->setModel('LandmarkTrip');
$lt->setMasterField('trip_id', $curr_trip);
}
}
and one last file which allows the list to change the grid
Create a file called trips_univ.js in wwwroot/website/templates/js
trip_univ.js
$.each({
viewTrip: function(url, name){
document.location.href=url+'&trip='+$(name).val();
}
},$.univ._import);
So now, you can create trips using the CRUD to add, edit and delete rows.
Then go to the itinerary page to select a trip from the dropdown list or it defaults to the earliest trip and can add, remove or edit landmarks from the trip.

As you have solved your problem partially, I just need to add some notes on how to incorporate multiple actions into the form.
$form->setModel('Trip');
$form->addField('line','extrainfo'):
if($form->isSubmitted()){
$form->update();
$it=$this->add('Model_Itinerary');
$it->set('trip_id', $form->getModel()->get('id'));
$it->set('extrainfo', $form->get('extrainfo'));
$it->update();
}
This way you can create multiple models when the form is saved.

Related

Oracle Spatial search query error for SDO_WITHIN_DISTANCE (lat/long based)

I need to perform location based search based on latitude and longitude pairs, to find out the near by locations of stores within a radius/distance of given KMs.
I am to use (for certain) Oracle's SDO_GEOMETRY for searching the locations.
Also, the table structure are parent-child based such that store address (zip, lat/long) is in parent table but store details (name, contact, etc) are in the child table.
This is to make sure that we do not have redundant data (as multiple store can have same lat/long and by some dark magic same address)
I have the following scenario (tables provided):
Version - Oracle Database 12c Enterprise Edition Release 12.2.0.1.0
Table: STORE_LOCATION
CREATE TABLE STORE_LOCATE
(
ID NUMBER DEFAULT STORE_LOCATE.nextval,
POSTAL_CODE VARCHAR2(18) NOT NULL,
ADDRESS VARCHAR2(382) NOT NULL,
GEO_LOCATION SDO_GEOMETRY NOT NULL
);
Table: STORE_DETAIL
CREATE TABLE STORE_DETAIL
(
ID NUMBER DEFAULT STORE_DETAIL_SEQ.nextval,
STORE_CODE VARCHAR2(20) NOT NULL,
STORE_NAME VARCHAR2(150) NOT NULL,
IS_ACTIVE NUMBER(3) DEFAULT 0 NOT NULL,
fk_store_locate_id INT NOT NULL. -- FK to ID of parent
);
I have inserted data in parent as:
INSERT INTO STORE_LOCATE (ZIP, ADDRESS, GEO_LOCATION) VALUES
('567875', '84 Paddar Road',
SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (80.34234431,26.12354422, NULL), NULL, NULL));
Likewise, child table has entries:
INSERT INTO STORE_DETAIL (STORE_CODE, STORE_NAME, FK_STORE_LOCATION_ID) VALUES
('ST01', 'STORE 1', 1);
So, now when a user shares his location to me (lat/long), I need to search all nearby locations of stores within a specified radius.
I tried the following query, but I am getting error with this:
SELECT
s.store_code,
s.store_name,
loc.zip,
loc.address,
loc.geo_location
FROM store_detail s,
store_locate loc
where MDSYS.SDO_WITHIN_DISTANCE(loc.geo_location,
(MDSYS.SDO_GEOMETRY(2001, 8307,
MDSYS.SDO_POINT_TYPE(80.21456732,26.23117864, NULL) ,NULL, NULL)),
'distance=1000 unit=KM') = 'TRUE';
Getting the below error:
ORA-29900: operator binding does not exist
ORA-06553: PLS-306: wrong number or types of arguments in call to 'SDO_WITHIN_DISTANCE'
29900. 00000 - "operator binding does not exist"
*Cause: There is no binding for the current usage of the operator.
*Action: Change the operator arguments to match any of the existing
bindings or add a new binding to the operator.
I am breaking my head around this for a while now but in vain.
Ref:
https://issues.redhat.com/browse/TEIID-751?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
https://docs.oracle.com/cd/E17781_01/appdev.112/e18750/xe_locator.htm#XELOC562
Q's:
Is this the correct way to perform location search on Oracle SQL?
Is there any other way if the above is incorrect?
There are a number of syntax errors in your code (POSTAL_CODE called ZIP, etc)
Here is the corrected example (I also removed the sequences for simplicity)
CREATE TABLE STORE_LOCATE (
ID NUMBER primary key,
POSTAL_CODE VARCHAR2(18) NOT NULL,
ADDRESS VARCHAR2(382) NOT NULL,
GEO_LOCATION SDO_GEOMETRY NOT NULL
);
CREATE TABLE STORE_DETAIL (
ID NUMBER primary key,
STORE_CODE VARCHAR2(20) NOT NULL,
STORE_NAME VARCHAR2(150) NOT NULL,
IS_ACTIVE NUMBER(3) DEFAULT 0 NOT NULL,
fk_store_locate_id INT NOT NULL references STORE_LOCATE
);
INSERT INTO STORE_LOCATE (ID, POSTAL_CODE, ADDRESS, GEO_LOCATION) VALUES (1, '567875', '84 Paddar Road', SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE (80.34234431,26.12354422, NULL), NULL, NULL));
INSERT INTO STORE_DETAIL (ID, STORE_CODE, STORE_NAME, FK_STORE_LOCATE_ID) VALUES (1001,'ST01', 'STORE 1', 1);
commit;
Here is running your query:
SELECT
s.store_code,
s.store_name,
loc.postal_code,
loc.address,
loc.geo_location
FROM store_detail s, store_locate loc
where SDO_WITHIN_DISTANCE(
loc.geo_location,
SDO_GEOMETRY(2001, 8307,
SDO_POINT_TYPE(80.21456732,26.23117864, NULL),NULL, NULL
),
'distance=1000 unit=KM'
) = 'TRUE';
STORE_ STORE_NAME POSTAL ADDRESS GEO_LOCATION(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES
------ ---------- ------ -------------------- ----------------------------------------------------------------------------------
ST01 STORE 1 567875 84 Paddar Road SDO_GEOMETRY(2001, 8307, SDO_POINT_TYPE(80.3423443, 26.1235442, NULL), NULL, NULL)
1 row selected.
The error you get probably means Oracle Spatial is not or incorrectly installed in your database. What exact database version do you use ?
IMPORTANT NOTE:
Those queries really need a spatial index on the GEO_LOCATION column. Without one, the query is rejected in versions up to 12.1. From 12.2 and later, the query will run, but will be very slow as soon as the number of locations goes above a few 100s. Once you go into the 100000 or more, it will be very slow.
See https://docs.oracle.com/en/database/oracle/oracle-database/19/spatl/indexing-querying-spatial-data.html#GUID-07129836-0DAE-4BCC-B290-942C456AE2EA for details

Some SQLite tables can not be created, but others (using the same approach) can

I am making an Electron application, which uses an SQLite Database. Inside of the app's directory, I have a folder named db and as a child, another one - seeder. In that seeder directory there are a bunch of .sql files, needed for creating the db architecture and seeding the database with information needed:
Electron App/
|---main.js
|---index.html
|---node_modules
|---package.json
|---db/
|---seed.js
|---seeder/
|---bunch of .sql files
When I run seed.js it is supposed to get all filenames inside of seeder/ and run every single one successively. The files are named as follows:
01.tables.sql
02.countries.sql
03.ekatte.sql - (this one contains all the villages and cities in Bulgaria)
04.programmes.sql
05.schedules.sql
06.subjects.sql
Everything works as expected, except one thing: 01.tables.sql is supposed to create all the tables, and all other files contain INSERT INTO statements. Some of the tables are not created and when the Electron app tries to INSERT INTO them - sqlite returns an error: no such table (but only for oblasti, programmes, schedules and subjects).
Here are the contents of 01.table.sql:
CREATE TABLE countries (
countryID integer NOT NULL CONSTRAINT countries_pk PRIMARY KEY,
countryName text NOT NULL,
countryISO text NOT NULL
);
CREATE TABLE grades (
gradeID integer NOT NULL CONSTRAINT grades_pk PRIMARY KEY,
gradeValue integer NOT NULL,
gradeStudent integer NOT NULL,
gradeSchedule integer NOT NULL
);
CREATE TABLE oblasti (
oblastID integer NOT NULL CONSTRAINT oblasti_pk PRIMARY KEY,
oblastName text NOT NULL,
oblastCode text NOT NULL
);
CREATE TABLE obshtini (
obshtinaID integer NOT NULL CONSTRAINT obshtini_pk PRIMARY KEY,
obshtinaName text NOT NULL,
obshtinaOblast integer NOT NULL
);
CREATE TABLE programmes (
programmeID integer NOT NULL CONSTRAINT programmes_pk PRIMARY KEY,
programmeName text NOT NULL
);
CREATE TABLE schedules (
scheduleID integer NOT NULL CONSTRAINT schedules_pk PRIMARY KEY,
scheduleProgramme integer NOT NULL,
scheduleSemester integer NOT NULL,
scheduleSubject integer NOT NULL
);
CREATE TABLE selishta (
selishteID integer NOT NULL CONSTRAINT selishta_pk PRIMARY KEY,
selishteName text NOT NULL,
selishteObshtina integer NOT NULL,
selishteOblast integer NOT NULL
);
CREATE TABLE students (
studentID integer NOT NULL CONSTRAINT students_pk PRIMARY KEY,
studentName text NOT NULL,
studentFamily text NOT NULL,
studentPicture blob NOT NULL,
studentBirthplace integer,
studentForeignCountry integer,
studentForeignOblast text,
studentForeignObshtina text,
studentForeignSelishte text,
studentEGN integer NOT NULL,
studentAddress text NOT NULL,
studentPhone text NOT NULL,
studentNationality integer NOT NULL,
studentEduForm integer NOT NULL,
studentOKS integer NOT NULL,
studentSemester integer NOT NULL,
studentClass integer NOT NULL,
studentFakNomer integer NOT NULL,
studentStatus integer NOT NULL,
studentValid integer NOT NULL
);
CREATE TABLE subjects (
subjectID integer NOT NULL CONSTRAINT subjects_pk PRIMARY KEY,
subjectName text NOT NULL
);
and this is the part of seed.js, responsible for the actual seeding:
const db = new sqlite3.Database('db/database.db');
fs.readdir('db/seeder/', function(err, dir) {
let fileList = new Array();
$.each(dir, function(index, fileName){
fileList.push(fileName);
});
fileList.sort();
seedDB(fileList);
});
function seedDB(files){
if(files.length > 0){
let fileName = files.shift();
fs.readFile('db/seeder/'+fileName, 'utf-8', function(err, data){
db.serialize(function() {
db.run(data);
});
seedDB(files);
});
}
}

I don't know what is wrong. Check if 2 users are friends in laravel

i'm new in working with mvc frameworks. I am currently learning Laravel and i'm stuck. I need to make my model check if two users are friends.
I have the following database:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`firstname` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `users` (`id`, `firstname`) VALUES
(1, 'name1'),
(2, 'name2'),
(3, 'name3'),
(4, 'name4');
CREATE TABLE `friends` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id_from` int(10) unsigned NOT NULL,
`user_id_to` int(10) unsigned NOT NULL,
`status` enum('pending','accepted','blocked') NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id_from` (`user_id_from`),
KEY `user_id_to` (`user_id_to`)
);
INSERT INTO `friends` (`id`, `user_id_from`, `user_id_to`, `status`) VALUES
(1, 1, 3, 'accepted'),
(2, 1, 2, 'pending'),
(3, 4, 1, 'pending'),
(4, 4, 2, 'pending'),
(5, 3, 4, 'accepted');
And my model Friend looks like this:
class Friend extends Eloquent
{
public $user_id;
public $user_id_from;
public $friends;
public $friend_user_id;
public function check_friend($user_id, $friend_user_id){
$this->user_id = $user_id;
$this->friend_user_id = $friend_user_id;
$this->friends = DB::select('
SELECT
fu.id AS `friend_uid`
FROM
`users` AS `us`
LEFT JOIN
`friends` AS `fr`
ON
(fr.user_id_from = us.id OR fr.user_id_to = us.id)
LEFT JOIN
`users` AS `fu`
ON
(fu.id = fr.user_id_from OR fu.id = fr.user_id_to)
WHERE
fu.id != us.id
AND
fr.status = "accepted"
AND
us.id = ?', array($this->user_id));
return in_array($this->friend_user_id, $q);
}
}
Controller:
public function get_checkfriend(){
$friend = new Friend;
return $friend->check_friend(1,2);
}
I am getting the following error: in_array() expects parameter 2 to be array, object given.
I var dumped the second parameter (which should be my result from the query) but there is a totaly different thing inside (not data from the database).
Problem is i don't know what am i doing wrong. Please help
First of all, since you're using Laravel you should be using its built-in database functionality. Use the Schema builder to generate your database: http://laravel.com/docs/schema
Second, make use of Eloquent's built in functionality for database relationships: http://laravel.com/docs/eloquent#many-to-many
A quick example for your case would be something like this (I think):
// app/models/user.php
class User extends Eloquent
{
public function friends() {
return $this->belongsToMany('User', 'friends', 'user_id', 'friend_id');
}
}
// app/database/schema/user.php
Schema::create('users', function($table)
{
$table->increments('id');
$table->string('name');
// and any other stuff you want in your user database
});
// app/database/schema/friend.php
Schema::create('friends', function($table)
{
$table->increments('id');
$table->integer('user_id');
$table->integer('friend_id');
});

Enable foreign key support for Sqlite3 in CakePHP

I have enabled foreign keys in SQLITE using PRAGMA foreign_keys = ON; and have confirmed it's working below.
sqlite> PRAGMA foreign_keys = ON;
sqlite> CREATE TABLE transactions (
...> id integer primary key,
...> amount REAL,
...> item TEXT,
...> created DATETIME,
...> modified DATETIME,
...> date DATE,
...> time TIME,
...> description TEXT,
...> transaction_type_id INTEGER,
...> category_id INTEGER,
...> account_id INTEGER,
...> location_id INTEGER,
...> FOREIGN KEY (transaction_type_id) REFERENCES transaction_types(id),
...> FOREIGN KEY (category_id) REFERENCES categories(id),
...> FOREIGN KEY (account_id) REFERENCES accounts(id),
...> FOREIGN KEY (location_id) REFERENCES locations(id)
...> );
sqlite> INSERT INTO transactions VALUES (null, '5.0', 'test', '2013-06-11 18:33:56', '2013-06-11 18:33:56', '2013-06-11', '18:33:00', 'test description', 2, 1, 2, 1);
sqlite> SELECT * FROM categories;
1|fsfs|2013-06-11 18:33:38|2013-06-11 18:33:38
sqlite> SELECT * FROM transactions JOIN categories ON transactions.category_id=categories.id;
4|5.0|test|2013-06-11 18:33:56|2013-06-11 18:33:56|2013-06-11|18:33:00|test description|2|1|2|1|1|fsfs|2013-06-11 18:33:38|2013-06-11 18:33:38
sqlite> DELETE FROM categories WHERE id=1;
Error: foreign key constraint failed
sqlite>
However, when I try to do this through CakePHP, I get no errors about foreign key constraints and the category is deleted. Below are my Transaction and Category models.
Transaction.php:
class Transaction extends AppModel {
public $belongsTo = array('Location', 'TransactionType', 'Category', 'Account');
....
Category.php:
class Category extends AppModel {
public $hasMany = array('Transaction', 'Budget');
....
My delete function for Category in CategoriesController.php is done through a component function and they are as follows.
CategoriesController.php -> delete
public function delete($id) {
$this->Crud->delete($this, $id, "Category");
}
CrudComponent.php -> delete
public function delete($current, $id, $modelName) {
$className = strtolower(Inflector::humanize($modelName));
if ($current->request->is('get')) {
throw new MethodNotAllowedException();
}
if ($current->$modelName->delete($id)) {
$current->Session->setFlash('The '.$className.' with id: ' . $id . ' has been deleted.');
$current->redirect(array('action' => 'index'));
}
}
I think my associations are set up fine as I have no problems retrieving data. However, the foreign keys are not being obeyed on delete.
I suspect it's something to do with having to run "PRAGMA foreign_keys=ON" every time CakePHP connects to the database but I'm not sure how to do this. Or it might be something wrong with my Model definitions and associations.
I'm using CakePHP version 2.3.5 and Sqlite3 version 3.7.13.
Any help would be greatly appreciated!
Thank you :)

yii CActiveRecord with()

I have the following code and the when I call my find method it shows me this: "Invalid argument supplied for foreach()" in CActiveFinder at line 784:
$pk=array();
784 foreach($this->_pkAlias as $name=>$alias)
785 {
786 if(isset($row[$alias]))
787 $pk[$name]=$row[$alias];
788 else // no matching related objects
789 return null;
790 }
791 $pk=serialize($pk);
It fails when it reaches this code:
$objCampanie = $modelCampanii->with('stocs')->findAll();
Relations from class Campanii:
* #property Stoc[] $stocs
* #property Vanzari[] $vanzaris
public function relations()
{
return array(
'stocs' => array(self::HAS_MANY, 'Stoc', 'id_campanie'),
'vanzaris' => array(self::HAS_MANY, 'Vanzari', 'id_campanie'),
);
}
Relations from class Stoc
* #property Produse $codProdus
* #property Campanii $idCampanie
* #property Vanzari[] $vanzaris
public function relations()
{
return array(
'codProdus' => array(self::BELONGS_TO, 'Produse', 'cod_produs'),
'idCampanie' => array(self::BELONGS_TO, 'Campanii', 'id_campanie'),
'vanzaris' => array(self::HAS_MANY, 'Vanzari', 'cod_produs'),
);
}
Where is the problem? Why does it not retrieves my code?
Table structure:
Campanii:
CREATE TABLE IF NOT EXISTS `campanii` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nume` varchar(255) NOT NULL,
`data_comanda` date NOT NULL,
`data_scadenta` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
Stoc:
CREATE TABLE IF NOT EXISTS `stoc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_campanie` int(11) NOT NULL,
`cod_produs` varchar(10) NOT NULL,
`cantitate` int(11) NOT NULL,
`pret` double NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `id_campanie` (`id_campanie`),
KEY `cod_produs` (`cod_produs`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
--
-- Constraints for table `stoc`
--
ALTER TABLE `stoc`
ADD CONSTRAINT `stoc_ibfk_1` FOREIGN KEY (`id_campanie`) REFERENCES `campanii` (`id`),
ADD CONSTRAINT `stoc_ibfk_2` FOREIGN KEY (`cod_produs`) REFERENCES `produse` (`cod`);
The problem was due to a missing primary key in the stoc table. The reason why follows:
private function populateRecord($query,$row)
{
// determine the primary key value
if(is_string($this->_pkAlias)) // single key
{
if(isset($row[$this->_pkAlias]))
$pk=$row[$this->_pkAlias];
else // no matching related objects
return null;
}
else // is_array, composite key
{
$pk=array();
foreach($this->_pkAlias as $name=>$alias)
{
if(isset($row[$alias]))
$pk[$name]=$row[$alias];
else // no matching related objects
return null;
}
$pk=serialize($pk);
}
...
The above code is from CActiveFinder. As you can see, if the _pkAlias of a table is not a string, then it assumes it's an array, without checking to see if any primary key exists at all.
Therefore, when you call with('stocs'), CActiveFinder tries to populate the related records (meaning, populateRecord is called), which tries to figure out the PK as part of its normal process, and so fails due to the lack of a PK.
Ultimately, it is the result of an incorrect assumption in the framework code. It can be worked around (as you found) by simply creating a PK.
You can look at CActiveFinder, starting on line 385, to see how the value of _pkAlias is set.
https://github.com/yiisoft/yii/blob/1.1.13/framework/db/ar/CActiveFinder.php
I get same error in CActiveFinder(834) after Yii framework update from 1.1.11 to 1.1.14. All was worked before update, all primary keys was setted.
After some struggling I found that errors is gone when I cleaned my YiiCache (I have CDbCache enabled in my config).
TRUNCATE YiiCache or DELETE FROM YiiCache

Resources