WHen i try to do :
$fields = array('id' => 'custom_id', 'title' => 'some_name');
The result I get has id as a string.
If I do:
$fields = array('custom_id', 'title' => 'some_name');
then it gives custom_id as integer.
How can I obtain custom_id as id without loosing the data type. I read the documentation but didn't found much help.
There is something that virtual fields can do I think. But is it possible inside the find query without the use of virtual fields etc?
Thanks in Advance
As of CakePHP 3.2
you can use Query::selectTypeMap() to add further types, which are only going to be used for casting the selected fields when data is being retrieved.
$query = $table
->find()
->select(['alias' => 'actual_field', /* ... */]);
$query
->selectTypeMap()
->addDefaults([
'alias' => 'integer'
]);
You can use any of the built-in data types, as well as custom ones. In this case the alias field will now be casted as an integer.
See also
API > \Cake\Database\Query::selectTypeMap()
Cookbook > Database Access & ORM > Database Basics > Data Types
Cookbook > Database Access & ORM > Database Basics > Adding Custom Types
With CakePHP 3.1 and earlier
you'll have to use Query::typeMap(), which will not only affect the selected field when data is being retrieved, but in various other places too where data needs to be casted according to the field types, which might cause unwanted collisions, so use this with care.
$query
->typeMap()
->addDefaults([
'alias' => 'integer'
]);
See also
API > \Cake\Database\Query::typeMap()
Change the type of existing columns
Changing the type of an existing column of a table is possible too, however they need to be set using a specific syntax, ie in the column alias format used by CakePHP, that is, the table alias and the column name seprated by __, eg, for a table with the Articles alias and a column named id, it would be Articles__id.
This can be either set manually, or better yet retrieved via Query::aliasField(), like:
// $field will look like ['Alias__id' => 'Alias.id']
$field = $query->aliasField('id', $table->alias());
$query
->selectTypeMap()
->addDefaults([
key($field) => 'string'
]);
This would change the the default type of the id column to string.
See also
API > \Cake\Datasource\QueryInterface::aliasField()
Hi my alternative example full, user schema() in controller Users add type column aliasFiels by join data:
$this->Users->schema()
->addColumn('is_licensed', [
'type' => 'boolean',
])
->addColumn('total_of_licenses', [
'type' => 'integer',
]);
$fields = [
'Users.id',
'Users.username',
'Users.first_name',
'Users.last_name',
'Users.active',
'Users__is_licensed' => 'if(count(LicenseesUsers.id)>=1,true,false)',
'Users__total_of_licenses' => 'count(LicenseesUsers.id)',
'Users.created',
'Users.modified',
'Languages.id',
'Languages.name',
'Countries.id',
'Countries.name',
'UserRoles.id',
'UserRoles.name',
];
$where = [
'contain' => ['UserRoles', 'Countries', 'Languages'],
'fields' => $fields,
'join' => [
'LicenseesUsers' => [
'table' => 'licensees_users',
'type' => 'LEFT',
'conditions' => [
'Users.id = LicenseesUsers.users_id'
],
],
],
'group' => 'Users.id'
];
// Set pagination
$this->paginate = $where;
// Get data in array
$users = $this->paginate($this->Users)->toArray();
Related
I'm rebuilding a vanilla PHP/MySQL application using CakePHP 3.5.13.
One of the queries in the original application needs to build a JOIN condition on the same table and does so by using separate table aliases. The query is as follows - and gives the correct results that we expect:
SELECT DISTINCT(s.id) FROM substances s
JOIN display_substances AS dsUses
ON (s.id = dsUses.substance_id AND dsUses.display_id = 128 AND (dsUses.value LIKE '%dye%') )
JOIN display_substances AS displays
ON (s.id = displays.substance_id AND displays.display_id NOT IN (1,2,3,4,6,128) AND (displays.value LIKE '%bpr%'))
The reason this is needed is because the query is doing a search for 2 separate items of user input - within the same table (display_substances) but against different display_substances .display_id fields. In terms of the query above it means:
Search for "%dye%" where display_id = 128
Search for "%bpr%" where display_id is not 1,2,3,4,6 or 128
In Cake I have written it like this in a Controller that handles the search functionality:
$query = $Substances->find()->select(['id' => 'Substances.id'])->distinct();
// Search for "dye"
$query = $query->matching('DisplaySubstances', function ($q) use ($uses_summary) {
return $q->where([
'DisplaySubstances.value LIKE' => '%dye%', // "dye" is dynamic and comes from $uses_summary
'DisplaySubstances.display_id' => 128
]);
});
// Search for "bpr"
$query = $query->matching('DisplaySubstances', function ($q) use ($regulatory_information) {
return $q->where([
'DisplaySubstances.value LIKE' => '%bpr%', // "bpr" is dynamic and comes from $regulatory_information
'DisplaySubstances.display_id NOT IN' => [1,2,3,4,6,128]
]);
});
This produces the wrong SQL, because when I debug $query->sql(); it gives a different JOIN condition:
INNER JOIN display_substances DisplaySubstances ON
(
DisplaySubstances.value like "%dye%" AND DisplaySubstances.display_id = 128
AND DisplaySubstances.value like "%bpr%"
AND DisplaySubstances.display_id not in (1,2,3,4,6,128)
AND Substances.id = (DisplaySubstances.substance_id)
)
I'm not sure how to rewrite this query such that it will treat each of the two search inputs as a JOIN condition, as per the original query.
The main thing I've noticed is that the original query has separate aliases for the same table (AS dsUses and AS displays). I'm not sure if this is relevant?
I'm trying to use the ORM as opposed to writing the SQL manually so would prefer to know how to use it to do this.
It's not yet possible to specify custom aliases for matching() calls, currently multiple matching() calls on the same association will merge the conditions as can be seen in your generated SQL snippet.
For now you'd have to either create additional associations (ie additionally to your DisplaySubstances association in your SubstancesTable class) with different aliases:
$this->hasMany('DsUses', [
'className' => 'DisplaySubstances'
]);
$this->hasMany('Displays', [
'className' => 'DisplaySubstances'
]);
on which you can then match:
$query->matching('DsUses', function ($q) use ($regulatory_information) {
return $q->where([
'DsUses.value LIKE' => '%dye%',
'DsUses.display_id' => 128
]);
});
$query->matching('Displays', function ($q) use ($regulatory_information) {
return $q->where([
'Displays.value LIKE' => '%bpr%',
'Displays.display_id NOT IN' => [1, 2, 3, 4, 6, 128]
]);
});
or build the joins manually, for example using innerJoin():
$query->innerJoin(
[
'DsUses' => 'display_substances'
],
[
'Substances.id' => new \Cake\Database\Expression\IdentifierExpression('DsUses.substance_id'),
'DsUses.display_id' => 128,
'DsUses.value LIKE' => '%dye%'
],
[
'DsUses.display_id' => 'integer',
'DsUses.value' => 'string'
]
);
$query->innerJoin(
[
'Displays' => 'display_substances'
],
[
'Substances.id' => new \Cake\Database\Expression\IdentifierExpression('Displays.substance_id'),
'Displays.display_id NOT IN' => [1, 2, 3, 4, 6, 128],
'Displays.value LIKE' => '%bpr%'
],
[
'Displays.display_id' => 'integer',
'Displays.value' => 'string'
]
);
See also
cakephp/cakephp#9499 : Improve association data fetching
Cookbook > Database Access & ORM > Query Builder > Adding Joins
I'm using Cake's $table->find('list') finder method to retrieve an array of associated users [id => name]. Have used it in the past and its worked well. In this find I'm containing a belongsToMany table and retrieving [id => name].
In \App\Model\Table\SitesTable::initialize the ClientUsersWithAuthorities belongsToMany relationship is defined
$this->belongsToMany('ClientUsersWithAuthorities', [
'className' => 'AppUsers',
'joinTable' => 'sites_client_users',
'foreignKey' => 'site_id',
'targetForeignKey' => 'user_id',
'propertyName' => 'client_users_with_authorities']);
In \App\Controller\ClientGroupsController::getClientgroupUsers
$siteClientUsers = $this->Sites->find('list', [
'keyField' => 'client_users_with_authorities.id',
'valueField' => 'client_users_with_authorities.full_name'])
->where(['id' => $siteId])
->contain(['ClientUsersWithAuthorities'])
->toArray();
$siteClientUsers returns [0 => null] instead of [1234 => 'Client 1 name', 5678 => 'Client 2 name'] as expected. Both users exist in the join table.
Three other methods (below) return the array I'm looking for and which I'm expecting $this->Sites->find('list') to produce.
The cookbook describes associated data can be listed.
https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#finding-key-value-pairs
So why isn't $this->Sites->find('list') producing the expected array?
mapReduce
$mapper = function ($data, $key, $mapReduce) {
if (!empty($data['client_users_with_authorities'])) {
foreach ($data['client_users_with_authorities'] as $user) {
$mapReduce->emit($user);
}}};
$siteClientUsers = $this->Sites->find('list', [
'keyField' => 'id',
'valueField' => 'full_name'])
->where(['id' => $siteId])
->contain(['ClientUsersWithAuthorities'])
->mapReduce($mapper)
->toArray();
Hash::combine
$siteClientUsers = $this->Sites->find('all')
->where(['id' => $siteId])
->contain(['ClientUsersWithAuthorities'])
->toArray();
$siteClientUsers = Hash::combine($siteClientUsers,'{n}.client_users_with_authorities.{n}.id', '{n}.client_users_with_authorities.{n}.full_name');
Temp belongsTo relationship on the join table
$table = $this->getTableLocator()->get('SitesClientUsers');
$table->belongsTo('Users', [
'className' => 'AppUsers',
'foreign_key' => 'user_id']);
$siteClientUsers = $table->find('list', [
'keyField' => 'Users.id',
'valueField' => 'Users.full_name'
])
->select(['Users.id', 'Users.full_name'])
->where(['SitesClientUsers.site_id' => $siteId])
->contain(['Users'])
->toArray();
The Cookbook says:
You can also create list data from associations that can be reached with joins
The important part being "that can be reached with joins", which isn't the case for belongsToMany associations. Given that list transformation happens on PHP level, the description should maybe focus on that instead, but it's still kinda valid as it stands.
client_users_with_authorities will be an array, ie possibly multiple records, so you cannot use it to populate a parent record - one Sites record represents one list entry. If you want to find a list of ClientUsersWithAuthorities that belongs to a specific site, then you can either use one of your other solutions (or something similar to that), or you could for example query from the other side of the association and use a matcher on Sites:
$query = $this->Sites->ClientUsersWithAuthorities
->find('list', [
'keyField' => 'id',
'valueField' => 'full_name'
])
->matching('Sites', function (\Cake\ORM\Query $query) use ($siteId) {
return $query->where([
'Sites.id' => $siteId
]);
})
->group('ClientUsersWithAuthorities.id');
This would create joins based on Sites.id, so that you'd only retrieve the ClientUsersWithAuthorities that are associated with Sites where Sites.id matches $siteId.
See also
Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data
I've got something like this
$query = Customer::find()
->select(['customer.name', 'surname', 'cityName' => 'cities.name', 'streetName' => 'streets.name'])
->joinWith(['city', 'street'])
->where(['group_id' => $id]);
When i do
return $query->all();
it returns only columns from customer table, but when i do something like this
$raw = $query->createCommand()->getRawSql();
return \Yii::$app->user_db->createCommand($raw)->queryAll();
it returns me all 4 columns. Why orm fails?
I'm using custom db connection (user), dynamicly connected after authorization. Anyway ActiveRecord->getDb() has been customized too and it works well till now.
it returns only columns from customer table, but when i do something like this.
Yes, that's right. Because Yii2 AR(Active Record) is ORM pattern. And it's try to return all result off query like object.
So, I will not tell the theory, I'd better suggest a solution variant:
$query = Customer::find()
->joinWith(['city', 'street'])
->where(['group_id' => $id])
->asArray()
->all();
return $query;
It's from Yii2 docs(performance tuning).
The result will be like:
[
all data selected from "customer",
['city' => all data selected from city joinWith],
['street' => all data selected from street joinWith]
]
I think, this is exactly what you need.
But, if you need objects. You can try marge objects to only one array.
$customer = Customer::find()
->joinWith(['city', 'street'])
->where(['group_id' => $id])
->all();
return [
'customer' => $customer,
'city' => $customer->city,
'street' => $customer->street,
];
you are using
->select(['customer.name', 'surname', 'cityName' => 'cities.name', 'streetName' => 'streets.name'])
so you will get selected columns only.
use,
$query = Customer::find()
->joinWith(['city', 'street'])
->where(['group_id' => $id])
->all();
this will give you all the columns
WHen i try to do :
$fields = array('id' => 'custom_id', 'title' => 'some_name');
The result I get has id as a string.
If I do:
$fields = array('custom_id', 'title' => 'some_name');
then it gives custom_id as integer.
How can I obtain custom_id as id without loosing the data type. I read the documentation but didn't found much help.
There is something that virtual fields can do I think. But is it possible inside the find query without the use of virtual fields etc?
Thanks in Advance
As of CakePHP 3.2
you can use Query::selectTypeMap() to add further types, which are only going to be used for casting the selected fields when data is being retrieved.
$query = $table
->find()
->select(['alias' => 'actual_field', /* ... */]);
$query
->selectTypeMap()
->addDefaults([
'alias' => 'integer'
]);
You can use any of the built-in data types, as well as custom ones. In this case the alias field will now be casted as an integer.
See also
API > \Cake\Database\Query::selectTypeMap()
Cookbook > Database Access & ORM > Database Basics > Data Types
Cookbook > Database Access & ORM > Database Basics > Adding Custom Types
With CakePHP 3.1 and earlier
you'll have to use Query::typeMap(), which will not only affect the selected field when data is being retrieved, but in various other places too where data needs to be casted according to the field types, which might cause unwanted collisions, so use this with care.
$query
->typeMap()
->addDefaults([
'alias' => 'integer'
]);
See also
API > \Cake\Database\Query::typeMap()
Change the type of existing columns
Changing the type of an existing column of a table is possible too, however they need to be set using a specific syntax, ie in the column alias format used by CakePHP, that is, the table alias and the column name seprated by __, eg, for a table with the Articles alias and a column named id, it would be Articles__id.
This can be either set manually, or better yet retrieved via Query::aliasField(), like:
// $field will look like ['Alias__id' => 'Alias.id']
$field = $query->aliasField('id', $table->alias());
$query
->selectTypeMap()
->addDefaults([
key($field) => 'string'
]);
This would change the the default type of the id column to string.
See also
API > \Cake\Datasource\QueryInterface::aliasField()
Hi my alternative example full, user schema() in controller Users add type column aliasFiels by join data:
$this->Users->schema()
->addColumn('is_licensed', [
'type' => 'boolean',
])
->addColumn('total_of_licenses', [
'type' => 'integer',
]);
$fields = [
'Users.id',
'Users.username',
'Users.first_name',
'Users.last_name',
'Users.active',
'Users__is_licensed' => 'if(count(LicenseesUsers.id)>=1,true,false)',
'Users__total_of_licenses' => 'count(LicenseesUsers.id)',
'Users.created',
'Users.modified',
'Languages.id',
'Languages.name',
'Countries.id',
'Countries.name',
'UserRoles.id',
'UserRoles.name',
];
$where = [
'contain' => ['UserRoles', 'Countries', 'Languages'],
'fields' => $fields,
'join' => [
'LicenseesUsers' => [
'table' => 'licensees_users',
'type' => 'LEFT',
'conditions' => [
'Users.id = LicenseesUsers.users_id'
],
],
],
'group' => 'Users.id'
];
// Set pagination
$this->paginate = $where;
// Get data in array
$users = $this->paginate($this->Users)->toArray();
I wrote 2 days ago to ask about andConditions and it appeared that I didn't understand the idea but the fact is that for two days now I am stuck with the next step using CakeDC:
How do I implement complex HABTM conditions in "query" methods for CakeDC search plugin?
I have Offer HABTM Feature (tables: offers, features, features_offers) and the below works just fine when used in controller:
debug($this->Offer->find('all', array('contain' => array(
'Feature' => array(
'conditions' => array(
'Feature.id in (8, 10)',
)
)
)
)
)
);
The problem comes when I want to use the same conditions in the search:
public $filterArgs = array(
array('name' => 'feature_id', 'type' => 'query', 'method' => 'findByFeatures'),
);
........
public function findByFeatures($data = array()) {
$conditions = '';
$featureID = $data['feature_id'];
if (isset($data['feature_id'])) {
$conditions = array('contain' => array(
'Feature' => array(
'conditions' => array(
'Feature.id' => $data['feature_id'],
)
)
)
);
}
return $conditions;
}
I get an error:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column
'contain' in 'where clause'
which makes me think that I cannot perform this search and/or use containable behavior in searches at all.
Can someone with more experience in the field please let me know if I am missing something or point me to where exactly to find a solution for that - perhaps a section in the cookbook?
EDIT: Also tried the joins. This works perfectly fine in the controller, returning all the data I need:
$options['joins'] = array(
array('table' => 'features_offers',
'alias' => 'FeaturesOffers',
'type' => 'inner',
'conditions' => array(
'Offer.id = FeaturesOffers.offer_id'
),
array('table' => 'features',
'alias' => 'F',
'type' => 'inner',
'conditions' => array(
'F.id = FeaturesOffers.feature_id'
),
)
),
);
$options['conditions'] = array(
'feature_id in (13)' //. $data['feature_id']
);
debug($this->Offer->find('all', $options));
... and when I try to put in the search method I get the returned conditions only in the where clause of the SQL
WHERE ((joins = (Array)) AND (conditions = ('feature_id in Array')))
...resulting in error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'joins' in 'where clause'
EDIT: Maybe I am stupid and sorry to say that but the documentation of the plugin sucks a ton.
I double, triple and quadruple checked (btw, have lost already 30 hours at least on 1 filed of the search form facepalm) and the stupid findByTags from the documentation still doesn't make any sense to me.
public function findByTags($data = array()) {
$this->Tagged->Behaviors->attach('Containable', array('autoFields' => false));
$this->Tagged->Behaviors->attach('Search.Searchable');
$query = $this->Tagged->getQuery('all', array(
'conditions' => array('Tag.name' => $data['tags']),
'fields' => array('foreign_key'),
'contain' => array('Tag')
));
return $query;
}
As I understand it
$this->Tagged
is supposed to be the name of the model of the HABTM association.
This is quite far from the standards of cakePHP though: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm
The way it is described here, says that you don't need another model but rather you associate Recipe with Ingredient as shown below:
class Recipe extends AppModel {
public $hasAndBelongsToMany = array(
'Ingredient' =>
array(
'className' => 'Ingredient',
'joinTable' => 'ingredients_recipes',
'foreignKey' => 'recipe_id',
'associationForeignKey' => 'ingredient_id',
'unique' => true,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
}
meaning that you can access the HABTM assoc table data from Recipe without needing to define model "IngredientRecipe".
And according to cakeDC documentation the model you need is IngredientRecipe and that is not indicated as something obligatory in the cakePHP documentation. Even if this model is created the HABTM assoc doesn't work properly with it - I tried this as well.
And now I need to re-write the search functionality in my way, using only cakePHP even though I spent already 30 hours on it... so unhappy. :(
Every time I come to do this in a project I always spend hours figuring out how to do it using CakeDC search behavior so I wrote this to try and remind myself with simple language what I need to do. I've also noticed that although Using the CakeDC search plugin with associated models this is generally correct there is no explanation which makes it more difficult to modify it to one's own project.
When you have a "has and belongs to many" relationship and you are wanting to search the joining table i.e. the table that has the two fields in it that joins the tables on either side of it together in a many-to-many relationship you want to create a subquery with a list of IDs from one of the tables in the relationship. The IDs from the table on the other side of the relationship are going to be checked to see if they are in that record and if they are then the record in the main table is going to be selected.
In this following example
SELECT Handover.id, Handover.title, Handover.description
FROM handovers AS Handover
WHERE Handover.id in
(SELECT ArosHandover.handover_id
FROM aros_handovers AS ArosHandover
WHERE ArosHandover.aro_id IN (3) AND ArosHandover.deleted != '1')
LIMIT 20
all the records from ArosHandover will be selected if they have an aro_id of 3 then the Handover.id is used to decide which Handover records to select.
On to how to do this with the CakeDC search behaviour.
Firstly, place the field into the search form:
echo $this->Form->create('Handover', array('class' => 'form-horizontal'));?>
echo $this->Form->input('aro_id', array('options' => $roles, 'multiple' => true, 'label' => __('For', true), 'div' => false, true));
etc...
notice that I have not placed the form element in the ArosHandover data space; another way of saying this is that when the form request is sent the field aro_id will be placed under the array called Handover.
In the model under the variable $filterArgs:
'aro_id' => array('name' => 'aro_id', 'type' => 'subquery', 'method' => 'findByAros', 'field' => 'Handover.id')
notice that the type is 'subquery' as I mentioned above you need to create a subquery in order to be able to find the appropriate records and by setting the type to subquery you are telling CakeDC to create a subquery snippet of SQL. The method is the function name that are going to write the code under. The field element is the name of the field which is going to appear in this part of the example query above
WHERE Handover.id in
Then you write the function that will return the subquery:
function findByAros($data = array())
{
$ids = ''; //you need to make a comma separated list of the aro_ids that are going to be checked
foreach($data['aro_id'] as $k => $v)
{
$ids .= $v . ', ';
}
if($ids != '')
{
$ids = rtrim($ids, ', ');
}
//you only need to have these two lines in if you have not already attached the behaviours in the ArosHandover model file
$this->ArosHandover->Behaviors->attach('Containable', array('autoFields' => false));
$this->ArosHandover->Behaviors->attach('Search.Searchable');
$query = $this->ArosHandover->getQuery('all',
array(
'conditions' => array('ArosHandover.aro_id IN (' . $ids . ')'),
'fields' => array('handover_id'), //the other field that you need to check against, it's the other side of the many-to-many relationship
'contain' => false //place this in if you just want to have the ArosHandover table data included
)
);
return $query;
}
In the Handovers controller:
public $components = array('Search.Prg', 'Paginator'); //you can also place this into AppController
public $presetVars = true; //using $filterArgs in the model configuration
public $paginate = array(); //declare this so that you can change it
// this is the snippet of the search form processing
public function admin_find()
{
$this->set('title_for_layout','Find handovers');
$this->Prg->commonProcess();
if(isset($this->passedArgs) && !empty($this->passedArgs))
{//the following line passes the conditions into the Paginator component
$this->Paginator->settings = array('conditions' => $this->Handover->parseCriteria($this->passedArgs));
$handovers = $this->Paginator->paginate(); // this gets the data
$this->set('handovers', $handovers); // this passes it to the template
If you want any further explanation as to why I have done something, ask and if I get an email to tell me that you have asked I will give an answer if I am able to.
This is not an issue of the plugin but how you build the associations. You need to properly join them for a search across these three tables. Check how CakePHP is fetching the data from HABTM assocs by default.
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables
Suppose a Book hasAndBelongsToMany Tag association. This relation uses
a books_tags table as join table, so you need to join the books table
to the books_tags table, and this with the tags table:
$options['joins'] = array(
array('table' => 'books_tags',
'alias' => 'BooksTag',
'type' => 'inner',
'conditions' => array(
'Books.id = BooksTag.books_id'
)
),
array('table' => 'tags',
'alias' => 'Tag',
'type' => 'inner',
'conditions' => array(
'BooksTag.tag_id = Tag.id'
)
)
);
$options['conditions'] = array(
'Tag.tag' => 'Novel'
);
$books = $Book->find('all', $options); Using joins allows you to have
a maximum flexibility in how CakePHP handles associations and fetch
the data, however in most cases you can use other tools to achieve the
same results such as correctly defining associations, binding models
on the fly and using the Containable behavior. This feature should be
used with care because it could lead, in a few cases, into bad formed
SQL queries if combined with any of the former techniques described
for associating models.
Also your code is wrong somewhere.
Column not found: 1054 Unknown column 'contain' in 'where clause'
This means that $Model->contain() is somehow called. I don't see such a call in your code pasted here so it must be somewhere else. If a model method can not be found this error usually happens with the field name as column.
I want to share with everyone that the solution to working with HABTM searches with the plugin lies here: Using the CakeDC search plugin with associated models
#burzum, the documentation is far from ok man. Do you notice the use of 'type' => 'checkbox' and that it is not mentioned anywhere that it is a type?
Not to mention the total lack of grammar and the lots of typos and missing prepositions. I lost 2 days only to get a grasp of what the author had in mind and bind the words in there. No comment on that.
I am glad that after 5 days on the uphill work I made it. Thanks anyway for being helpful.