Querying a model by a many_many relationship with Silverstripe DataModel - silverstripe

If i have a Model DebatePage which has the following many many relationship:
private static $many_many = array(
'Panelists' => 'Panelist'
);
and the panelist has a text field called "Name"
How can i query for all the debates that have a panelist called bob?
DebatePage::get()->filter('Panelist.Name:partialmatch', $keyword);
but i get an unknown column error

I was nearly there
DebatePage::get()->filter('Panelists.Name:partialmatch', $keyword);
So I just needed to use the relationship name, not singularised. Amazing how good SS data model is.

Related

Nested models not created as batman objects

Given the following models with one-to-many relationship:
class App.Post extends Batman.Model
#hasMany 'comments'
class App.Comment extends Batman.Model
#belongsTo 'post'
My comments are included in the JSON of the post from the backend. Since i'm having #encode 'comments' the comments are added to the post. However, they are added in an array of simple JS objects instead of an associationset of Batman objects.
Should I really decode them explicitly like this
#encode 'comments',
decode: (value, key, incomingJSON, outgoingAttributes, record) ->
outgoingAttributes = App.Comment.createMultipleFromJSON(incomingJSON.comments)
or am I doing something stupid here?
#hasMany "comments" should automatically set up an encoder to load comments from JSON.
Did you mention that you added your own encoder, like
#encode 'comments'
?
If so, that is overriding the one created by #hasMany 'comments'. Try removing the #encode 'comments'. Does that help?

Why to use doctrine relationships vs native query

I have a simple question. I saw a Symfony2-Tutorial where the blogger used everywhere simple entities without relations and was also using doctrine native-query to do joins and query the different entities.
What is better, to use doctrine native query or build every time relationships ?
Greetings Michael
I think that it depends on how the resultset will be handle. For example, suppose the following relationship:
a company has a lot of employees (1:N)
Just figure out the impact if this company has more than 10K employees when it does a select query in every request loading all employees data to be showed. In this scenario could be a good practice to create a lazy association in models:
<?php
/**
* #Entity
*/
class Company
{
/**
* #OneToMany(targetEntity="Employee", fetch="EXTRA_LAZY")
*/
public $employees;
}
At this case, doctrine only will triggered the required data from database, because it knows that all the data will be accessed gradually as you request it. You can read more about lazy associations in doctrine's docs.
How about the native queries?
Native queries can map arbitrary SQL code to objects, such as highly vendor-optimized SQL or stored-procedures. Fast scalar results and less ram usage. Take note that a complex model relationship could be too heavy for server to be manipulated. For example, look this structure based on Class Table Inheritance:
There is a super class called Product and there are more than 200 different sub-products that extends from Product. Each sub-product is storaged in its respective table.
<?php
abstract class Product
protected $name;
Some sub-products as example:
<?php
class Candy extends Product
/** specific property for this product */
private $sugarLevel;
Another one:
<?php
class IceCream extends Product
/** specific property for this product */
private $temperature;
Now, you need to assess every product in you depot. Normally, the first idea to get this resulst is doing:
$assess = array();
$products = $em->getRepository('models\Product');
foreach ($products as $p)
{
//summarize each product by type
$assets[$p->getType()] = $assets[$p->getType()] + 1;
}
echo "There are " . $assets['candy'] " candies in stock";
This is really heavy process because we are quering 200 tables just to determinate the existence of each product. This could be easy mitigated with a simple native query:
$query = $em->createNativeQuery('SELECT p.type, count(p.type) as total FROM Product p group by p.type', $rsm);
$result = $query->getArrayResult();
print_r($result);
// [0] => array('type' => 'candy', 'total' => 545),
// [1] => array('type' => 'icecream', 'total' => 344),
//...
// [199] => array('type' => 'foo', 'total' => 878),

Symfony2 Criteria filtering OneToMany

I have an Entity called 'User', which has a OnetoMany relation in a field called 'books'.
I also have an Entity called 'Book' which has many attributes, like, 'title' or 'date'.
There ir another entity called 'Date', which attributes are: 'day', 'month' and 'year'.
I want to filter the books that the user has which are from year 2009.
I am tring to do it like this, using Criteria, but I recieve an error because field date.year does not exist:
$books = $user->getBooks();
$criteria = Criteria::create()
->where(Criteria::expr()->eq("date.year", "2009"));
$books_2009 = $books->matching($criteria);
Any idea of how can I solve it?
$criteria = Criteria::create()
->where(Criteria::expr()->eq("year", "2009"));
This should work. Please let me know.

symfony2, form builder, how to initially display an empty entity select list

I have 3 entities: Make, Model and Auto. Make -> Model is oneToMany relation and Auto->Model is manyToOne relation.
What I want to achieve is to be able to generate a form that consist of list of Makes e.g Ford, Opel.. and initially load an empty list of Models. The Model list should be populated only when a Make is selected in the list, that is achieved by ajax call.
My question is what I need to do that Model list is initially empty since the form builder is populating with all models that are asigned in any Make.
I can achieve similar by using query_builder and let say search for a model that does not exist, but that's not the wright way.
class AutoType extends AbstractType {
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('make','choice', array(
'choices'=>Array('1'=>'Opel', '2'=>'Ford'),
'property_path'=>false,
'label'=>'Make'))
->add('model', 'entity', array( // this fetches all models. Also don't want a subset of models, just empty list with 'Select Model'
'class' => 'Auto\SalonBundle\Entity\Model',
'empty_value' => 'Select Model'
))
->add('km')
->add('cc')
->add('hp')
->add('kw')
);
}
}
In order to achieve that you have to create your own Form Type and corresponding _widget block. Or you can get there faster using the Dependent Filtered Form Type of the bundle https://github.com/shtumi/ShtumiUsefulBundle .

How to write Unit Test case for Zend Db Table Row

I am trying to write test case for my Row classes and I don't really what is the proper way to do that.
I've seen many example use model & table, for example http://techportal.inviqa.com/2010/12/07/unit-testing-databases-with-zend-framework/.
The case doesn't use Row at all and the model is all about getters and setters. I don't want rewrite such things as the Zend_Db_Table_Row can do it automatically.
My row classes are extended from Zend_Db_Table_Row, I don't think there is necessary to write test cases like getters & setters.
And most my row classes are like following
class App_Table_Row_User extends Zend_Db_Table_Row_Abstract {
}
Then, in order to get a better test case coverage, what kind of test case I should write for a class like above?
I presume you need to populate object's attributes (table's column name => values) and run tests for your custom methods.
Zend_Db_Table_Row_Abstract constructor has one parameter - associative array with following keys:
table
data
stored
readOnly
To build useful for testing object you should use at least the "data" entries. It is associative array too. The "data" array has column names as keys and row data as values. So the testing object setUp may look as follows:
$this->object = new App_Table_Row_User(
array(
'data' => array(
'username' => 'Jon Doe',
'password' => 'qwerty',
'email' => 'j.doe#example.com'
)
)
);
You can pass NULL as values in the "data" array entries if you need something similar to the fetchNew return object.
If you are using "save" or any method that requires the table model, I will suggest using mock/stub object and passing it as the "table" parameter in the constructor. You can control any Db related operation that way.
Hope that helps :)

Resources