Creating dropdownlist with relations in yii - php

I am a newbie in Yii framework and now I try to create dropdownlist from related table.
I have table "News"[...a lot of fields,category] and "NewsCategories"[id,category_name].
In form for creating new record in News I want to create a dropdownlist in category field when user can choose a category_name, but id of category have to be recorder in a new record.
Help me please with it. Sorry for my English. I hope what I explain it understandable.
Here is how I created relations
Model News.php
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'category'=>array(self::BELONGS_TO, 'NewsCategories', 'category'),
);
}
Model NewsCategories.php
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'news'=>array(self::HAS_MANY, 'News', 'id'),
);
}
And how I try to create dropdownlist:
<?php echo $form->dropDownList($model,'category',CHtml::listdata(News::model()->with('category')->findAll(),'id','category_name'),array('empty'=>'(Select a category')));?>

When specifying relations, you don't need to specify primary key (id), because yii can deduct primary key from the model. You only need to specify the other end, so your NewsCategory relation should look like this:
'news'=>array(self::HAS_MANY, 'News', 'category'),
To get data suitable for drop-down list, use
CHtml::listData(NewsCategories::model()->findAll(), 'id', 'category_name');

Related

Phalcon ORM field has relation with another field in same table

I have the following table in my mysql DB
I have a model Shipment and i am using Phalcon's ORM to interact with my DB. The master_id field in this table is actually the id of another raw, but in the same table, as you can see in the picture. The id=1 is the Master Shipment and id=2 and id=3 are Subshipments.
My model right now looks like this
class Shipment extends Model
{
protected $id;
protected $hawb;
protected $master_id;
public function initialize()
{
parent::initialize();
$this->hasMany(
'id',
'Shipment',
'master_id'
);
}
//setters and getters are here
}
When I am using $shipment = ShipmentModel::findFirst($id); in my Controller, i can see the master_id of the Shipment.
What i want to have is, call another function from my Shipment model in order to retrieve all the SubShipments as a Collection of Shipment models, or at least an array with Shipment models.
Or even better, if the ShipmentModel::findFirst($id); could populate the SubShipments automatically (if there are any) would be the best!
I don't really know if the $this->hasMany that I have is correct over there, so if someone could show me how to proceed I would be grateful :)
You need to provide full namespace, not just class name - to solve this Model 'Shipment' could not be loaded. Best is to add alias:
$this->hasMany(
'id',
Shipment::class,
'master_id',
['alias' => 'subShipments'])
);
And then just use:
Shipment::findFirst()->getSubShipments() you can add such method if you want and do return $this->getRelated('subShipments')

Laravel Foreign Key Constraint Errors when deleting Parent with data in child of child

So here's how this is set up.
A Step has a Category
A Category has a Section
A Section has Multiple Questions
I thought I had everything working in my model files, but unfortunately I'm running into an integrity error with my foreign keys.
My models are named:
Step.php
StepCategory.php
StepSection.php
StepQuestion.php
I'm not really sure how to set up my "many to one" relationships, or what belongs to what.
My database table names are as follows:
steps
step_categories
step_sections
step_questions
I'm running into this error when i'm deleting the parent entry of anything... If i delete a step, it should delete a category, the sections, and the questions associated with them. If i delete a category, it should delete the section and questions. If i delete a section it deletes all the questions.
In my step_categories table i have the foreign key column named as step_id.
In my step_sections table i have the foreign key column named as category_id.
In my step_questions table i have the foreign key column named section_id.
My foreign key name on my step_categories table is step_categories_step_id_foreign.
My foreign key name on my step_sections table is step_sections_category_id_foreign.
My foreign key name on my step_questions table is not set up yet as I have yet to make that part of the site yet. I'm currently stuck on the sections portion.
My destroy() function in my StepsController.php file is:
public function destroy($id)
{
// Find the step by the ID
$step = Step::find($id);
// Find all the categories and delete them.
$step->category()->delete();
// Delete the step
$step->delete();
// Flash the Session
Session::flash('success', 'The step has been successfully deleted.');
// Return Redirect to the index page
return redirect()->route('steps.index');
}
Heres how my models look so far... This is as far as I've gotten... :(
Step.php
class Step extends Model
{
// Tell the model what table to use
protected $table = 'steps';
// Define the relationship between steps and step categories
public function category() {
return $this->hasMany('App\StepCategory');
}
}
StepCategory.php
class StepCategory extends Model
{
// Tell the model what table to use
protected $table = 'step_categories';
// Define the relationship between step categories and steps
public function step() {
return $this->hasOne('App\Step', 'id', 'step_id');
}
// Define the relationship between steps categories and sections
public function section() {
return $this->hasMany('App\StepSection');
}
}
and my StepSection.php
class StepSection extends Model
{
// Tell the model what table to use
protected $table = 'step_sections';
// Define the relationship between step sections and step categories
public function category() {
return $this->hasOne('App\StepCategory', 'id', 'category_id');
}
}
So thats legit as much information as I can possibly give that I think will solve the problem. If you need anymore information to help me set up these relationships let me know.
So far I can delete a Step, and it will delete the category, so long as the category has no sections attached to it. However I can't delete the Step, or Category if it has any sections attached to it. :/ Don't know whats going on.
It looks like your problem is because of your tables, so make sure that when you declare a foreign key in your migrations you are adding what should be done on delete/update of those rows. For example:
On your step_categories the foreign key 'step_id' should be like this:
$table->foreign('step_id')->references('id')->on('step')->onDelete('cascade')->onUpdate('cascade');
You should do the same following with all your tables

Changing own id in pivot table

I'm developing a Laravel application where I have a posts table, a tags table and a post_tag table which acts as a pivot table.
Now I need to give all the tags from a post to another post. In other words I need to make:
$tags = $post->tags;
And change the post_id to each record in the pivot table. I have all the relationships already set.
EDIT: this is my code
class Post extends Model
{
public function tags()
{
return $this->belongsToMany(Tag::class)->withPivot('is_active')->withTimestamps();
}
}
class Tag extends Model { }
The main problem is that I have to keep the is_active value as it is. I just need to replace the post_id from the pivot table where post_id equals the one I want to override (I know I could make a raw query but I'm trying to avoid it)
EDIT 2:
I made it work this way but I still prefer an object oriented way
DB::table('post_tag')->where('post_id', $post_a->id)->update(['post_id' => $post_b->id]);
You can use the method updateExistingPivot of Eloquent, from the laravel documentation:
If you need to update an existing row in your pivot table, you may use updateExistingPivot method. This method accepts the pivot record foreign key and an array of attributes to update:
$user = App\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);
Try something like
$tags = $post->tags;
//convert tags to IDs only for upcoming steps
... //an array of IDs
$post->tags()->sync($tags); //remove the tags from this post
$post2->tags()->sync($tags); // add the tags to this post
This should get you to the right tracks.
Update
If it was only one, this would do
$post2->tags()->attach($tag, ['is_active' => true]);
$post2->tags()->->sync([1 => ['is_active' => true], 2 => ['is_active' => true]);
You can try to adapt the example above.
But I have no idea how to do it with an array of IDs.

Yii activeCheckBoxList

I have a strange probem
In AR model, Gift i have many_many relation with categories
'categories'=>array(self::MANY_MANY, 'GiftCategory',
'tbl_category_gift(gift_id, category_id)'),
And when i call $gift->categories it returns active record objects, and in database i see that values is stored correctly
But when i write
<? echo $form->checkBoxList($model, "categories", GiftCategory::listData()); ?>
In my checkboxlist only 1 value is selected if model have categories, i dont understand wtf is it, please, help :)
PROBLEM: Yii activeCheckBoxList displaying only 1 checked (only first)
It doesn't work because, in the words of the Yii creator Qiang:
...in activeListBox(), the second parameter should be an attribute
name, not a relation name. In your case, you may need to declare a new
property to store the selections.
I believe the same thing applies to activeCheckBoxList.
The way I solved this was as follows (this blog post was helpful Retrieving selected checkbox items in yii)
Add index option to your relation
'categories' => array(self::MANY_MANY,
'Category', 'post_category(post_id, category_id)','index'=>'id'),
Add a property to your model
public $selectedCategoryIds
Populate this attribute in afterFind
public function afterFind()
{
parent::afterFind();
$this->selectedCategoryIds = array_keys($this->categories);
}
Use this new "attribute in your view
<? echo $form->checkBoxList($model, "selectedCategoryIds", GiftCategory::listData()); ?>
In order to properly handle updating this data see Larry Ullman's article Handling Related Models in Yii Forms
<?php
echo CHtml::activeCheckBoxList($model, 'categories',
CHtml::listData(GiftCategory::model()->findAll(), 'id', 'title'),
array('checkAll' => ' Select All'));
?>

Using Multiple Tables in a Zend Model and returning a combined result set

Hi This is either a very specific or very generic quetion - I'm not sure, and I'm new to the Zend framework / oo generally. Please be patient if this is a stupid Q...
Anyway, I want to create a model which does something like:
Read all the itmes from a table 'gifts' into a row set
for each row in the table, read from a second table which shows how many have been bought, the append this as another "field" in the returned row
return the row set, with the number bought included.
Most of the simple Zend examples seem to only use one table in a model, but my reading seems to suggest that I should do most of the work there, rather than in the controller. If this is too generic a question, any example of a model that works with 2 tables and returns an array would be great!
thanks for your help in advance!
I assume second tables is something like "gift_order" or something.
In this case you need to specify tables relationships beetween "gift" and and "gift_order" via foreign keys and describe it in table class.
It will look like this
class GiftOrder extends Zend_Db_Table_Abstract
{
/** Table name */
protected $_name = 'gif_order';
protected $_referenceMap = array(
"Fileset" =>array(
"columns" => array("gifId"),
"refTableClass" => "Gift",
"refColumns" => array("id")
));
........................
You need to specify foreigh key constraint while create table with SQL
ALTER TABLE `gift_order`
ADD CONSTRAINT `order_to_gift` FOREIGN KEY (`giftId`) REFERENCES `gift` (`id`) ON DELETE CASCADE;
If this is something you looking for you could find more on this at this link link http://framework.zend.com/manual/en/zend.db.table.relationships.html
With such solution you will be able to loop gifts and get their orders without any complex SQL's
$rowSetGifts = $this->findGifts();
while($rowSetGifts->next()){
$gift = $rowSetGifts->current();
$orders = $gift->findGiftOrder();//This is magick methods, this is the same $gift->findDependentRowset('GiftOrder');
//Now you can do something with orders - count($orders), loop them or edit
}
I would recommend creating a function in your gifts model class that returns what you want. It would probably look something like:
public function getGiftWithAdditionalField($giftId) {
$select = $this->getAdapter()->select()
->from(array('g' => 'gifts'))
->joinLeft(array('table2' => 't2'), 'g.gift_id = t2.gift_id', array('field' => 'field'))
->where('g.gift_id = ?', $giftId);
return $this->getAdapter->fetchAll($select);
}
You can check out the Zend Framework Docs on Joins for more info.

Categories