PHP Active Record Update Relation Table - php

This is my many to many relation
class Post extends ActiveRecord\Model {
static $table_name = 'app_post';
static $has_many = array(
array('postcategory'),
array('category', 'through' => 'postcategory')
);
}
class Category extends ActiveRecord\Model {
static $table_name = 'app_post_category';
static $has_many = array(
array('post', 'through' => 'postcategory'),
array('postcategory')
);
}
class PostCategory extends ActiveRecord\Model {
static $table_name = 'app_post_category_relation';
static $belongs_to = array(
array('post'),
array('category')
);
}
To create new record in post i use
$post = Post::create(
array(
'title' => 'Title',
'description' => 'Description',
'keyword' => 'key,word'
)
);
$post->create_postcategory(array('category_id' => '1'));
$post->create_postcategory(array('category_id' => '3'));
But i dont know how to update this record ?
$post = Post::find(1);
$post->title = 'Some title';
$post->save();
It's just update post table how about relation table ?

Related

has_many and has_one relation SilverStripe

I followed the tutorial on https://www.silverstripe.org/learn/lessons/working-with-data-relationships-has-many?ref=hub to create some featured items for my homepage. But somehow I missed one piece, because I get this error
[Error] Uncaught Exception: No has_one found on class 'HomePageFeatured', the has_many relation from 'HomePage' to 'HomePageFeatured' requires a has_one on 'HomePageFeatured'
HomePage.php
<?php
/**
* Defines the HomePage page type
*/
class HomePage extends Page {
// private static $db = array(
// );
// private static $has_one = array(
// );
private static $has_many = array (
'Featured' => 'HomePageFeatured'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Featured', GridField::create(
'Featured',
'Hervorgehobene Produkte',
$this->Featured(),
GridFieldConfig_RecordEditor::create()
));
return $fields;
}
private static $icon = "themes/hstheme/images/treeicons/home";
}
class HomePage_Controller extends Page_Controller {
}
HomePageFeatured.php
<?php
/**
* Holds the featured items from the Homepage
*/
class HomePageFeatured extends DataObject {
private static $db = array(
'Title' => 'Varchar',
'Description' => 'Text'
);
private static $has_one = array(
'Photo' => 'Image',
'HomePageFeatured' => 'HomePageFeatured'
);
public function getCMSFields() {
$fields = FieldList::create(
TextField::create('Title'),
TextareaField::create('Description'),
$uploader = UploadField::create('Photo')
);
$uploader->setFolderName('featured-photos');
$uploader->getValidator()->setAllowedExtensions(array('png','gif','jpeg','jpg'));
return $fields;
}
}
As I understand, the problem is the $has_one from HomePageFeatured.php. But it has a reference from HomePageFeatured.
HomePageFeatured needs a has_one of 'HomePage'
class HomePageFeatured extends DataObject {
private static $has_one = array(
'Photo' => 'Image',
'Parent' => 'HomePage',
);
}

Silverstripe custom search

I have a product catalog. There are:
Dzial.php - category page
class Dzial extends Page {
...
static $has_many = array(
'Marka' => 'Marka'
);
function getCMSFields() {
...
$gridField = new GridField("Marka", "marki:", $this->Marka(), $gridFieldConfig);
$fields->addFieldToTab("Root.Marki", $gridField);
PodDzial.php - subcategory page
class PodDzial extends Page {
.....
static $has_many = array(
'Kategoria' => 'Kategoria',
'Produkt' => 'Produkt'
);
function getCMSFields() {
....
$gridField = new GridField("Produkt", "Produkty:", $this->Produkt(), $gridFieldConfig);
$fields->addFieldToTab("Root.Produkty", $gridField);
$gridField2 = new GridField("Kategoria", "Kategoria:", $this->Kategoria(), $gridFieldConfig);
$fields->addFieldToTab("Root.Kategorie", $gridField2);
Produkt.php - product - DataObjects which belong to PodDzial.php
class Produkt extends DataObject {
.....
static $has_one = array (
'PodDzial' => 'PodDzial',
'Marka' => 'Marka',
'Kategoria' => 'Kategoria'
);
Kategoria.php - type of product- which belong to PodDzial (has_one) and to Produkt (has_many)
class Kategoria extends DataObject {
....
private static $has_one = array( 'PodDzial' => 'PodDzial' );
private static $has_many = array ('Produkt' => 'Produkt' );
Marka.php - brand of product- which belong to Dzial (has_one) and to Produkt (has_many)
class Marka extends DataObject {
...
private static $has_one = array( 'Dzial' => 'Dzial' );
private static $has_many = array ('Produkt' => 'Produkt');
I work on custom search for Produkt's on PodDzial page.
The code which doesn't work properly:
class Produkt extends DataObject {
...
public function getDefaultSearchContext() {
$fields = new FieldList(
DropdownField::create(
'MarkaID',
'Marka',
Marka::get()->map('ID','Title')
)->setEmptyString('--Wybierz marke--') ,
DropdownField::create(
'KategoriaID',
'Kategoria',
Kategoria::get()->filter(array('PodDzialID' => $this->PodDzialID))->map('ID','Title')
)->setEmptyString('--Wybierz kategorie--')
);
$filters = array(
'MarkaID' => new ExactMatchFilter('MarkaID'),
'KategoriaID' => new ExactMatchFilter('KategoriaID')
);
return new SearchContext(
$this->class,
$fields,
$filters
);
}
Both dropdown fields are working bad. They should list Kategoria's only from its PodDzial holder and Marka's from parent Dzial. Marka's field shows all Marka even from other categories now. Kategoria show nothing.
I use those same dropdowns on fieldlist. Kategoria's work ok. It shows only data from given PodDzial. Markas are on parent holder (Dzial) and I cant access it there too :
class Produkt extends DataObject {
....
$xxx = 'LEFT JOIN `SiteTree` ON `SiteTree`.ParentID=`Marka`.DzialID';
function getCMSFields(){
$fields = FieldList::create(
TabSet::create("Root",
Tab::create("Main",
....
DropdownField::create(
'MarkaID',
'Marka',
Marka::get()->filter($xxx, array('DzialID' => 'ParentID'))->map('ID','Title')
)->setEmptyString('-- None --'),
DropdownField::create(
'KategoriaID',
'Kategoria',
Kategoria::get()->filter(array('PodDzialID' => $this->PodDzialID))->map('ID','Title')
)->setEmptyString('-- None --')
Can anyone help?

ModelAdmin Customization of Searchable fields

I got a many to many relationship between Products and Categories using Silverstripes' ORM. All is working except when I try to add a Category for a product the choices for Category is shown by user id instead of Category name. I tried to map ID to name but did not work. Below is what I tried, what am I missing?
class Product extends DataObject {
private static $db = array(
'ProductName' => 'Varchar(32)',
);
private static $many_many = array (
'Category' => 'Category'
);
}
class Category extends DataObject {
private static $db = array(
'Category' => 'Varchar(32)',
);
public function searchableFields() {
return array (
'Category' => array (
'filter' => 'ExactMatchFilter',
'title' => 'Category',
'field' => 'TextField'->setSource(
$this::get()->map('ID','Category')
)
)
);
}
private static $belongs_many_many = array (
'Product' => 'Product'
);
}
When Silverstripe needs to display a shorthand for a DataObject, it will call the getTitle() method on that DataObject.
getTitle() will first check if the DataObject has a Title field and return that value if it does.
If your DataObject doesn't have Title field, it will try searching for a Name field.
If it can't find a Name field either, it will default to returning the ID of your DataObject, which is probably what is happening for you.
How to fix your specific example
There's 2 ways you can fix your specific example:
Rename your DataObjects DB fields to Name or Title
Override the getTitle() method on your 2 DataObjects
Solution #1
class Product extends DataObject {
private static $db = array(
'Name' => 'Varchar(32)',
);
private static $many_many = array (
'Category' => 'Category'
);
}
class Category extends DataObject {
private static $db = array(
'Name' => 'Varchar(32)',
);
public function searchableFields() {
return array (
'Category' => array (
'filter' => 'ExactMatchFilter',
'title' => 'Category',
'field' => 'TextField'->setSource(
$this::get()->map('ID','Category')
)
)
);
}
private static $belongs_many_many = array (
'Product' => 'Product'
);
}
Solution #2
class Product extends DataObject {
private static $db = array(
'ProductName' => 'Varchar(32)',
);
private static $many_many = array (
'Category' => 'Category' );
public function getTitle() {
return $this->ProductName;
}
}
class Category extends DataObject {
private static $db = array(
'Category' => 'Varchar(32)',
);
public function searchableFields() {
return array (
'Category' => array (
'filter' => 'ExactMatchFilter',
'title' => 'Category',
'field' => 'TextField'->setSource(
$this::get()->map('ID','Category')
)
)
); }
private static $belongs_many_many = array (
'Product' => 'Product' );
public function getTitle() {
return $this->Category;
}
}
Which solution is best?
In your specific case, I would go with solution #1, because your DB fields are functionally name/title fields.
I would use solution #2 if my DataObject's title needs to use many fields. Let's say you a have Person DataObject with a first name and a last name:
public function getTitle() {
return $this->FirstName . ' ' . $this->LastName;
}

CakePHP: Show other field instead of id

I'm working in a web aplication for board role playing games management. Its very simple for now.
I have 3 tables:
(1) Game
* id
* title
* user_id (game master)
(2) Sheet
* id
* name
* game_id
* user_id
(3) Users
* id
* username
Well, I have two problems:
1 - In Sheet view, i cant show the game tittle or the user name, just his id's
2 - In Game view, I cant show the user name (the game master).
I try a lot of answers found here for similar problems, but nothing works. I'm i little bit frustrated :( please help.
Here my code details:
MODELS:
/*User Model*/
class User extends AppModel {
public $name = 'User';
public $hasMany = array(
'Sheet' => array(
'className' => 'Sheet',
'foreignKey' => 'user_id'
),
'Game' => array(
'className' => 'Game',
'foreignKey' => 'user_id'
)
);
}
/*Game Model*/
class Game extends AppModel {
public $name = 'Game';
public $belongsTo = array(
'Master' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
public $hasMany = array (
'Chars' => array (
'className' => 'Sheet',
'foreignKey' => 'game_id'
)
);
}
/*Sheet Model*/
class Sheet extends AppModel {
public $name = 'Sheet';
public $belongsTo = array (
'Party' => array (
'className' => 'Game',
'foreignKey' => 'game_id'
),
'Player' => array (
'className' => 'User',
'foreignKey' => 'user_id'
)
);
}
CONTROLLERS:
/*SheetController*/
class SheetController extends AppController {
public $helpers = array('Html', 'Form');
var $name = 'Sheets';
public function view($id = null) {
$this->Sheet->id = $id;
$this->Sheet->recursive = 2;
if (!$this->Ficha->exists()) {
throw new NotFoundException(__('La ficha no existe'));
}
$this->set('sheet', $this->Sheet->read(null, $id));
}
}
class PartidasController extends AppController {
public $helpers = array('Html', 'Form');
var $name = 'Partidas';
public function view($id) {
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
$this->Partida->recursive=2;
$partida = $this->Partida->findById($id);
if (!$partida) {
throw new NotFoundException(__('Invalid post'));
}
$this->set('partida', $partida);
}
}
VIEWS:
/*Game View*/
<?php echo $game['Game']['title']; ?>
<strong>Master: </strong>
<?php
echo $this->Html->link($game['Game']['user_id'], array('controller' => 'Users','action' => 'view',$game['Game']['user_id'])); ?>
/*Sheet View*/
<?php echo $this->Html->link($sheet['Sheet']['nombreFicha'],array('controller' => 'sheets', 'action' => 'view', $sheet['Sheet']['id']));?>
<?php echo $this->Html->link($sheet['Sheet']['user_id'],array('controller' => 'users', 'action' => 'view', $sheet['Sheet']['user_id'])); ?>
<?php echo $this->Html->link($sheet['Sheet']['game_id'],array('controller' => 'games', 'action' => 'view', $sheet['Sheet']['game_id'])); ?>

Kohana and ORM relationship has_many_through

I have problem with Kohana 3.3 and ORM relationship has_many_through. I have two models
Model_Category
class Model_Category extends ORM {
protected $_table_name = 'category';
protected $_primary_key = 'category_id';
protected $_has_many = array(
'question' => array(
'model' => 'Question',
'through' => 'cat_question'
),
);
}
Model_Question
class Model_Question extends ORM {
protected $_table_name = 'question';
protected $_primary_key = 'question_id';
protected $_has_many = array(
'category' => array(
'model' => 'Category',
'through' => 'cat_question'
),
);
}
And in table cat_question there are two columns, category_id, question_id,
in table question: question_id, title, content, date,
in category: category_id, name
But it's not working preety good.. When i do it like that
$orm = ORM::factory('Question')->find_all();
foreach($orm as $el) {
var_dump($el->category->name);
}
They shows me NULL, but I don't know why.
I handle with this,
Question model should be looks like that :
class Model_Question extends ORM {
protected $_table_name = 'question';
protected $_primary_key = 'question_id';
protected $_has_many = array(
'category' => array(
'model' => 'Category',
'through' => 'cat_question',
'far_key' => 'category_id',
'foreign_key' => 'question_id',
),
);
}
And Category models
class Model_Category extends ORM {
protected $_table_name = 'category';
protected $_primary_key = 'category_id';
protected $_has_many = array(
'question' => array(
'model' => 'Question',
'far_key' => 'question_id',
'through' => 'cat_question',
'foreign_key' => 'category_id'
),
);
}
And if we want all category with count question is in, do something like that:
public function get_category_and_question() {
$orm = ORM::factory('Category');
$find = $orm->find_all();
foreach ($find as $element) {
$count = ORM::factory('Category', $element->category_id)->question->count_all();
$new_array[] = array(
'name' => $element->name,
'id' => $element->category_id,
'how_much' => $count
);
}
return $new_array;
}
I'm not pretty sure if that is really good solve but is not bad for me.
The problem is, that has_many_through means many-to-many. So one Category holds multiple Questions and vice versa. Now if you had followed Kohana's standards, your db name would be categories, questions, categories_questions and the name would be a plural, so accessible via categories or questions.
But you didn't, to work your code needs to look like the following
$orm = ORM::factory('Question')->find_all();
foreach($orm as $el)
{
$categories = $el->category->find_all();
foreach ($categories as $category)
{
var_dump($category->name);
}
}

Categories