Zend CASCADE on many-to-many relationship - many-to-many

I'm using the default Zend_Db_Table_Abstract to set the relationships. These are my models:
Model_Table_Project:
protected $_name = 'projects';
protected $_dependentTables = array('Model_Table_ProjectStage');
protected $_referenceMap = array(
'User' => array(
'columns' => 'userId',
'refTableClass' => 'Model_Table_User',
'refColumns' => 'id'
)
);
public function deleteProject($id)
{
$row = $this->find($id)->current();
if ($row)
{
$row->delete();
}
else
{
throw new Zend_Exception('Cannot delete project.');
}
}
Model_Table_Stage:
protected $_name = 'stages';
protected $_dependentTables = array('Model_Table_ProjectStage');
Model_Table_ProjectStage:
protected $_name = 'projectstage';
protected $_referenceMap = array(
'Project' => array(
'columns' => 'projectId',
'refTableClass' => 'Model_Table_Project',
'refColumns' => 'id',
'onDelete' => self::CASCADE,
),
'Stage' => array(
'columns' => 'stageId',
'refTableClass' => 'Model_Table_Stage',
'refColumns' => 'id',
'onDelete' => self::CASCADE,
)
);
Now when I want to delete a project, using the deleteProject() method in Model_Table_Project, it deletes the entry in the Project table and the entries in the ProjectStage table, but it doesn't delete the entries in the Stage table.
What am I doing wrong?

I've found the solution. It was a thinking error of myself. The solution I now use is:
In the Table model I call $row->delete() and in the Row model I declared a delete method:
public function delete()
{
$stages = $this->getStages();
foreach ($stages as $stage)
{
$stage->delete();
}
return parent::delete();
}
This way it first delete all relating stages and then it deletes itself.

Related

CakePHP not respecting foreignKey name

I have an articles table with a column tagging_id that needs to reference the id column in a table called tracking_categories as a foreign key.
My Article.php file has the following:
class Article extends AppModel {
public $controllerPath = 'articles';
public $useTable = 'articles';
var $binds = array(
'TrackingCategory' => array(
'bindType' => 'belongsTo',
'className' => 'TrackingCategory',
'foreignKey' => 'tagging_id'
),
'Channel' => array(
'bindType' => 'belongsTo',
'className' => 'Channel',
'foreignKey' => 'channel_id'
)
);
My TrackingCategory.php looks like this:
class TrackingCategory extends AppModel {
public $useTable = 'tracking_categories';
I have the following in the AppModel which Article.php inherits:
function expects($binds, $reset = false) {
if (func_num_args() > 2 || !is_bool($reset)) {
throw new InvalidArgumentException('Did you mean to pass an
array of binds?');
}
if (!is_array($binds)) {
$binds = array($binds);
}
foreach ($binds as $bind) {
if (isset($this->binds[$bind])) {
$tmp = array($this->binds[$bind]['bindType'] => array($bind => $this->binds[$bind]));
$this->bindModel($tmp, $reset);
}
}
}
I am getting the following error:
Database Error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Article.tracking_category_id' in 'field list'
It is still looking for the column named parsed via CakePHP's naming convention rather than the name that I explicitly set via the foreignKey value. What am I missing here?
The right syntax should be:
public $belongsTo = array(
'TrackingCategory' => array(
'className' => 'TrackingCategory',
'foreignKey' => 'tagging_id',
)
);
For more information, see CakePHP 2.x - Associations: Linking Models Together - belongsTo.

Insert or update in laravel?

What would be the best way to set this query? i can't seem to find any documentation on an actual insert or update that works, I'm hoping to do it via the Eloquent model but can't seem to get it working
any help would be appreciated.
DB::table('questions')->insert([
'marital_status' => $request->marital_status,
'job_title' => $request->job_Title,
'industry' => $request->industry,
'occupation' => $request->occupation,
'paye' => $request->paye,
'self_employed' => $request->self_employed,
'child_benefit' => $request->child_benefit,
'work_home' => $request->work_home,
'own_transport' => $request->own_transport,
'company_vehicle' => $request->company_vehicle,
'annual_income' => $request->annual_income,
'pay_memberships' => $request->pay_memberships,
'income_benefits' => $request->income_benefits,
'printer' => $request->printer,
'contact' => $request->contact,
'share' => $request->share,
'terms' => $request->terms,
'user_id' => $user
]);
here is my Model for Questions
<?php
namespace App;
class Questions extends Model
{
protected $fillable = [
'marital_status',
'job_title',
'industry',
'occupation',
'paye',
'self_employed',
'child_benefit',
'work_home',
'own_transport',
'company_vehicle',
'annual_income',
'pay_memberships',
'income_benefits',
'printer',
'contact',
'share',
'terms',
'user_id'
];
public function users(){
return $this->hasOne('App\User');
}
}
Use Eloquent with mass assignment:
Question::updateOrCreate($request->all()->put('user_id', $user));
Or:
$question = Question::firstOrNew('some_id', $someId);
$question->fill($request->all()->put('user_id', $user))->save();
Don't forget to fill $fillable array with all properties you want to persist:
class Question extends Model
{
protected $fillable = [
'marital_status',
'job_title',
'industry',
'occupation',
'paye',
'self_employed',
'child_benefit',
'work_home',
'own_transport',
'company_vehicle',
'annual_income',
'pay_memberships',
'income_benefits',
'printer',
'contact',
'share',
'terms',
'user_id'
]
Update
If put() method doesn't work for some reason, try this:
$request->merge(['user_id' => $user]);
And then just use $request->all()
Or:
$requestData = $request->all();
$requestData['user_id'] = $user;
And then use $requestData

How to implement filtering of a CGridView table for an ENUM columnt in Yii?

In a Yii application I display the data as a table. I use CGridView, that deals for me with (search based) data filter and sorting. It works.
Now I added an ENUM column status to the user database table. In the grid I can sort and filter this, but only by the value in the table. Well, it makes sense. But the user don't actually know, how it's saved n the database and works with (and wants to sort and filter by) labels.
Is there a way to provide sorting and filtering by custom labels for an ENUM database table column in Yii (using a CActiveRecord model and a CGridView generated data grid)?
database table
CREATE TABLE `users` (
`userid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(45) NOT NULL,
...
`status` enum('processed', 'waiting') NOT NULL,
PRIMARY KEY (`userid`),
UNIQUE KEY `email_UNIQUE` (`email`)
);
User model
/**
* ...
* #property string $userid
* #property string $email
* ...
* #property string $status
*/
class User extends CActiveRecord
{
public function tableName()
{
return 'users';
}
public function getFirstAndLastName(){
return CHtml::encode($this->firstname." ".$this->lastname);
}
public function rules()
{
return array(
...
array('userid, email, status', 'safe', 'on'=>'search'),
);
}
public function attributeLabels()
{
return array(
'userid' => 'Userid',
'email' => 'Email',
...
'status' => Yii::t('app', 'status'),
);
}
public function relations()
{
return array(
...
);
}
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('userid',$this->userid,true);
$criteria->compare('email',$this->email,true);
...
$criteria->compare('status',$this->status,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
"pagination"=>array(
"pageSize"=>25
)
));
}
public static function model($className=__CLASS__)
{
return parent::model($className);
}
protected function beforeSave()
{
return parent::beforeSave(); // TODO: Change the autogenerated stub
}
public function getProcessingStatus()
{
return Yii::t('app', $this->processing_status);
}
}
UserController
class UserController extends Controller
{
...
/**
* Manages all models.
*/
public function actionAdmin()
{
// Yii::app()->cache->flush();
$model=new User('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['User']))
$model->attributes=$_GET['User'];
$this->render('admin',array(
'model'=>$model,
));
}
...
}
view
...
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'user-grid',
'dataProvider' => $model->search(),
'filter' => $model,
'columns' => array(
'email',
'status',
array(
'class' => 'CButtonColumn',
'template' => '{view}{update}',
'buttons' => array(
'view' => array(
)
),
),
),
));
Model:
class User extends CActiveRecord {
const STATUS_PROCESSED = 'processed';
const STATUS_WAITING = 'waiting';
public static function getStatusList(){
return array(
self::STATUS_PROCESSED => 'Processed',
self::STATUS_WAITING => 'Waiting',
);
}
public function getStatusValue(){
$list = self::getStatusList();
return array_key_exists( $this->status, $list ) ? $list[ $this->status ] : 'Undefined';
}
}
View:
$this->widget('zii.widgets.grid.CGridView', array(
// other params
'columns' => array(
// other columns
array(
'name' => 'status',
'value' => '$data->getStatusValue()',
'filter' => User::getStatusList(),
),
)
));
That's all
You can specify a custom filter in your CDataColumn, by setting the filter property to be an array. It will result in a dropdown list filter instead of a text field filter.
Example:
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'user-grid',
'dataProvider' => $model->search(),
'filter' => $model,
'columns' => array(
'email',
array(
'name' => 'status',
'filter' => array(
'processed' => 'Processed',
'waiting' => 'Waiting',
),
),
array(
'class' => 'CButtonColumn',
'template' => '{view}{update}',
'buttons' => array(
'view' => array(
)
),
),
),
));
Also check out the docs

Phalcon ORM showing that the column is ambiguous when traversing model relationships

I am using Phalcon to query some relations between models.
I have the following models:
<?php
class Client extends ModelBase
{
private $id;
private $code;
private $active;
public function initialize()
{
parent::initialize();
$this->hasManyToMany(
"id",
"ClientAddress",
"client_id",
"address_id",
"Address",
"id",
array("alias" => "addresses")
);
public function getAddresses($params = null) {
return $this->getRelated("addresses", $params);
}
}
class Address extends ModelBase
{
private $id;
.......
<?php
class ClientAddress extends ModelBase
{
private $id;
private $active;
public function initialize()
{
parent::initialize();
$this->belongsTo("client_id", "Client", "id", array(
"alias" => "client"
));
$this->belongsTo("address_id", "Address", "id", array(
"alias" => "address"
));
}
}
I am receiving the below error:
The column 'id' is ambiguous, when preparing: SELECT [Address].* FROM [Address] INNER JOIN [ClientAddress] ON [ClientAddress].[address_id] = [Address].[id] WHERE [ClientAddress].[client_id] = ?0 AND id = ?1
The code that generates this error is:
$client = Client::findFirst(array(
"conditions" => "id = ?1",
"bind" => array( 1 => $current_client_id )
));
$addresses = $client->getAddresses(array(
"conditions" => "id = ?1",
"bind" => array( 1 => $id )
));
Why is this happening? Do I not have my relations setup properly? I would have assumed that it would prefix my where clause with the table name?
I had the same problem than you. I fixed it by adding
$client = Client::findFirst(array(
"conditions" => "[ClientAddress].[id] = ?1",
"bind" => array( 1 => $current_client_id )
));
$addresses = $client->getAddresses(array(
"conditions" => "[Address].[id] = ?1",
"bind" => array( 1 => $id )
));
You have the following problem when you have the same column name of two different MySQL table

CakePHP find Queries with aliases SQLSTATE[42S22] Error

I'm having a weird problem with my relationships/aliases in CakePHP and now its preventing me from accessing my data correctly.
I have:
User hasMany CreatorModule (alias for Module)
User HABTM LearnerModule (alias for Module)
Module belongsTo Creator (alias for User)
Module HABTM Learner (alias for User)
And I'm trying to call:
$id = $this->Module->User->findByEmail($email);
$modules = $this->Module->findByUserId($id['User']['id']);
The queries that get generated aren't correct - the table-alias is wrong. I'm not sure which of the above is responsible but I get:
SELECT
`Creator`.`id`,
`Creator`.`email`,
`Creator`.`organization`,
`Creator`.`name`,
`Creator`.`password`,
`Creator`.`verified`,
`Creator`.`vcode`
FROM
`snurpdco_cake`.`users` AS `Creator`
WHERE
`User`.`email` = 'foo#example.com' # <--
LIMIT 1
I figured out that the error is that CakePHP should change 'User' in the WHERE clause to Creator, but doesn't, even if I use the alias. How do I complete this query correctly.
Further, as a related problem, I find that I can no longer use User in my model calls etc now that I have defined aliases. Is there a way around this?
EDIT: As requested, here is my model code defining the aliases:
class User extends AppModel {
public $name = 'User';
public $uses = 'users';
public $hasMany = array(
'OwnedModule' => array(
'className' => 'Module',
'foreignKey' => 'user_id',
'dependent' => true
));
public $hasAndBelongsToMany = array(
'LearnerModule' => array(
'className' => 'Module',
'joinTable' => 'modules_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'module_id',
'unique' => 'keepExisting',
));
//The rest of the Model
}
//Different file, condensed here for spacing
class Module extends AppModel {
public $name = 'Module';
public $belongsTo = array(
'Creator' => array(
'className' => 'User'));
public $hasAndBelongsToMany = array(
'Learner' => array(
'className' => 'User',
'joinTable' => 'modules_users',
'foreignKey' => 'module_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
));
//The rest of the Model
}
try
$id = $this->Module->Creator->find('first',
array('conditions' => array('Creator.email' => $email)
);
$modules = $this->Module->findByCreatorId($id['User']['id']);