By using cake-DC migration we can write migrations for string,integer
can we used ENUM also ???
I'm just two years late but take a look at this repository. There's a solution for use any data types not supported for CakePHP in migrations.
You'll have a base migration which extends CakeMigration in your application to use instead. It'll make a call for strategies named with the data type, for instance the ENUM type:
https://github.com/leonardolessa/mywallet/blob/master/app/Lib/Migrations/BaseMigration.php
Each strategy implements an interface:
https://github.com/leonardolessa/mywallet/blob/master/app/Lib/Migrations/StrategyInterface.php
The strategy itself just run an ALTER TABLE to add the not supported type in the table:
https://github.com/leonardolessa/mywallet/blob/master/app/Lib/Migrations/EnumStrategy.php
Just don't forget that if you may want use not supported types and cake bake you gonna have a bad time.
You can only use the data types that the database drivers of the CakePHP ORM support. Enum is not supported, use faked enum instead.
See http://api.cakephp.org/2.4/class-Mysql.html#$columns
array(
'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'),
'string' => array('name' => 'varchar', 'limit' => '255'),
'text' => array('name' => 'text'),
'biginteger' => array('name' => 'bigint', 'limit' => '20'),
'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'),
'float' => array('name' => 'float', 'formatter' => 'floatval'),
'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'),
'binary' => array('name' => 'blob'),
'boolean' => array('name' => 'tinyint', 'limit' => '1')
)
You could extend the Mysql source and add that type, but this will break cross-database compatibility of your app. But it is an unlikely case anyway.
Related
I added some content Fields which looks as it follows;
$temporaryColumnHC = array(
'my_type' => array(
'exclude' => 0,
'label' => 'My Type',
'config' => array(
'type' => 'select',
'renderType' => 'selectSingle',
'items' => array(
array('Bar', 'bar'),
array('Pie', 'pie'),
array('Donut', 'donut'),
array('Line', 'line'),
array('Bar 2', 'bar2'),
array('Bar 3', 'bar3'),
array('Bubble', 'bubble'),
)
)
),
'my_suffix' => array(
'exclude' => 0,
'label' => 'My Label Suffix',
'config' => array(
'type' => 'input',
'size' => 10,
'max' => 20
)
),
'my_source_url' => array(
'exclude' => 0,
'label' => 'Source URL',
'config' => array(
'type' => 'input',
'renderType' => 'inputLink'
)
),
'my_source' => array(
'exclude' => 0,
'label' => 'Source Text',
'config' => array(
'type' => 'text',
'cols' => 40,
'rows' => 15
)
),
);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns(
'tt_content',
$temporaryColumnHC
);
but on save I get the following error
error [1620]: Unknown column 'suffix' in 'field list'
What I have to do that this fields is saved in database
As mentioned already as a comment, TYPO3 complains that the column is missing in the Database.
Your extension should provide an ext_tables.sql which extends the Database Schema. See https://docs.typo3.org/m/typo3/reference-coreapi/10.4/en-us/ExtensionArchitecture/FilesAndLocations/Index.html#ext-tables-sql for further information.
The file always contains CREATE TABLE statements, which will be converted by TYPO3 do update the schema.
Updating the schema can be done through the install tool of TYPO3, or tools like TYPO3 console via command line.
Could someone tell me if I've missed something in this? It keeps throwing the error mentioned at the bottom after the code block.
function license_update_7101() {
$schema['license_agreements'] = array(
'description' => 'License User Agreements',
'fields' => array(
'license_id' => array(
'description' => 'Primary key for license records',
'type' => 'serial',
'not null' => TRUE,
'unsigned' => TRUE
),
'user_id' => array(
'description' => 'License agreed to by User ID',
'type' => 'int',
'not null' => FALSE,
'unsigned' => TRUE,
'default' => '0'
),
'product_id' => array(
'description' => 'Product ID that represents the product this agreement was assigned to.',
'type' => 'int',
'not null' => FALSE,
'unsigned' => TRUE,
'default' => '0'
),
'session' => array(
'description' => 'Session created during account creation.',
'type' => 'varchar',
'length' => 32,
'not null' => FALSE,
'default' => ''
),
'agreed' => array(
'description' => 'Represents if the license was agreed to or not',
'type' => 'int',
'size' => 'tiny',
'not null' => FALSE,
'unsigned' => TRUE,
'default' => '0'
),
'agreement_date' => array(
'description' => 'Date this license was agreed to by user.',
'type' => 'datetime',
'mysql_type' => 'DATETIME',
'disp-width' => '11',
'not null' => FALSE,
'default' => NULL
),
'blog_name' => array(
'description' => 'URL for actual product license belongs to.',
'type' => 'varchar',
'length' => '128',
'not null' => FALSE,
'default' => ''
),
'primary key' => array('license_id')
)
);
db_create_table('license_agreements', $schema['license_agreements']);
}
ERROR:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB [error]
server version for the right syntax to use near 'DEFAULT NULL
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8 COMMENT 'License' at line 9
Really would love to get this solved.
Thanks!
So, courtesy of having another dev come help me try to find what was blowing things up, I managed to discover the issue as we worked through it.
'primary key' => array('license_id')
I ended up noticing that that was embedded within the fields array and needed to be outside/after it.
So, the fix was as simple as moving that line down as an array element of the license_agreements array. Problem solved!
If I do this:
$cdata = $this->Party->find('first',
array('contain' => array(
'Person' => array(
'Employee' => array(
'Volunteer'),
'Title'))));
Debugger::dump($cdata, 10);
I get this:
array(
'Party' => array(
'id' => '9',
'save_bit' => true
),
'Person' => array(
'id' => '5',
'title_id' => '1',
'first_name' => 'bob',
'middle_name' => '',
'last_name' => 'brown',
'is_active' => false,
'date_of_birth' => '1999-07-07',
'gender' => 'M',
'party_id' => '9',
'Title' => array(
'id' => '1',
'title' => 'Ms',
'description' => ''
),
'Employee' => array(
'id' => '5',
'person_id' => '5',
'Volunteer' => array(
'id' => '5',
'employee_id' => '5'
)
)
)
)
But I really want to get this:
array(
'Party' => array(
'id' => '9',
'save_bit' => true,
'Person' => array(
'id' => '5',
'title_id' => '1',
'first_name' => 'bob',
'middle_name' => '',
'last_name' => 'brown',
'is_active' => false,
'date_of_birth' => '1999-07-07',
'gender' => 'M',
'party_id' => '9',
'Title' => array(
'id' => '1',
'title' => 'Ms',
'description' => ''
),
'Employee' => array(
'id' => '5',
'person_id' => '5',
'Volunteer' => array(
'id' => '5',
'employee_id' => '5'
)
)
)
)
)
This way the array is following the natural hierarchy of my database tables and also works with my website forms for saving and editing which I have declared like so:
echo $this->Form->input('Party.Person.first_name');
echo $this->Form->input('Party.Person.is_active');
Is it possible to do this with Containable, if so how? Thanks!
As already mentioned in my comment, you cannot change the way how containable formats the data, it will be formatted to the CakePHP conventions depending on your associations.
Changing the format would have to be done manually after the find operation, but there's actually no need to do that, instead stick to the conventions with regards to associations and form helper usage, that way CakePHP can automatically glue everything together as needed.
Assuming the association is Party hasMany Person, you should simply use Person.0.first_name in the form, that way the helper can properly populate the field, and when passed to Model::saveAll() or Model::saveAssociated() CakePHP can determine how things need to be saved based on the associations defined on your models.
See Saving Related Model Data (hasOne, hasMany, belongsTo) for more information.
I'm trying to slim down my finds queries, by specifying which fields to use. I don't understand how I can specify specific fields for my HABTM fields.
This is my find:
$lastviewed = $this->Lastviewedproduct->find('all', array(
'fields' => array(
'Lastviewedproduct.id', 'Lastviewedproduct.sessionid', 'Lastviewedproduct.product_id',
'Product.id', 'Product.name', 'Product.slug', 'Product.price',
//'Category.id',
//'Mediafile.*',
),
'conditions' => array(
'Lastviewedproduct.status' => 'active',
'Lastviewedproduct.sessionid' => $this->Session->read('Companyname.sessionid'),
'Product.hidden_on_site' => 0,
'Product.visibility' => 1,
'Product.status' => 'active',
),
'order' => 'Lastviewedproduct.modified DESC',
'limit' => 5,
'recursive' => 2,
));
This is what it returns:
(int) 2 => array(
'Lastviewedproduct' => array(
'id' => '97',
'sessionid' => '14035312318244955',
'product_id' => '2'
),
'Product' => array(
'id' => '2',
'name' => 'blokhut 2',
'slug' => 'blokhut-2',
'price' => '200.00',
'Category' => array(
(int) 0 => array(
'id' => '218',
'zosomodule_id' => '25',
'user_add_id' => '0',
'user_update_id' => '0',
'created' => '2013-11-27 10:00:00',
'modified' => '2013-11-27 10:00:00',
'status' => 'active',
'visibility' => true,
'parent_id' => '2',
'shipment_id' => '1',
'name' => 'Metalen Tuinbergingen ',
'slug' => 'metalen-tuinbergingen-',
'pagetitle' => 'Metalen Tuinbergingen ',
'content' => '<p class="p1"><span class="s1">Metalen tuinbergingen zijn een praktische en kwalitatieve oplossing voor meer bergruimte in uw tuin. Wij hebben diverse merken metalen bergingen zoals </span><span class="s2">Biohort</span><span class="s1"> en </span><span class="s2">Yardmaster</span><span class="s1">. Hier hebben wij tevens ook tuinkasten en opbergboxen van.</span></p>
<p class="p1"><span class="s1"><br /></span></p>
<p class="p1"><span class="s1">Mocht u op zoek zijn naar andere varianten tuinbergingen, bekijk dan ons gehele assortiment </span><span class="s2">tuinbergingen.</span></p>',
'metatitle' => 'Metalen tuinbergingen',
'metadescription' => null,
'discountoffer' => false,
'discount_normal' => '0.00',
'discount_max' => '0.00',
'discount_ideal' => '0.00',
'cost_rembours' => '0.00',
'in_mainmenu' => true,
'hide_sidebar' => false,
'show_block' => true,
'sort_order' => '0',
'ProductsCategory' => array(
'id' => '2',
'created' => '2014-01-01 10:00:00',
'modified' => '2014-01-01 10:00:00',
'product_id' => '2',
'category_id' => '218'
)
)
),
'Mediafile' => array()
)
),
I don't want all these Category fields, but only Category.id, Category.name and Category.slug for example. How do i say that in my find? As you can see I tried adding Category.id in my fields array, but then I get an error. I read something about containable, but I didn't get that working and I don't know if that is the solution.
Thanks in advance for your help!
You can use ContainableBehavior for this task. You should write something like this:
1 attach behavior
permanent
class Lastviewedproduct extends AppModel {
public $actsAs = array('Containable');
....
}
on demand
$this->Lastviewedproduct->Behaviors->load('Containable');
2 specify fields
$this->Lastviewedproduct->find('all', array(
'contain' => array(
'Product' => array(
'Category' => array(
'fields' => array('id','name','slug')
),
),
'Mediafile'
)
));
Add field parameter with relation ship where you give relationship to Category MODEL
public $hasMany = array(
'Category' => array(
'className' => 'Category',
'fields' => array('Category.id','Category.name','Category.slug')
)
);
As Dimitry said above - Containable is the way to go with this:
In your Models/AppModel.php (Create it if it doesn't exist) change the call to have the following:
class AppModel extends Model {
public $actsAs = array('Containable');
}
Then you would do as Dimitry said above - this will allow you to only return the fields you want.
'recursive' => 2
will eventually cause you so much slowness that your app will be painful to use, most people set recursive = 1 in their AppModel and use containable the rest of the time.
I have 3 tables: projects, project_reminder_users, project_types.
The relations is as follow:
Project => belong to => ProjectType
hasMany => ProjectReminderUser
ProjectReminderUser => belong to => Project
ProjectType => hasMany => Project
I get all data based on who assigned(ProjectReminderUser) by this
$this->Project->ProjectReminderUser->Behaviors->load('Containable');
$this->paginate = array(
'ProjectReminderUser' => array(
'limit' => $limit,
'contain' => array(
'Project' => array(
'ProjectComment',
'ProjectFile',
),
'User'
),
'conditions' => array(
'User.group_id' => $this->Session->read('Auth.User.group_id'),
'ProjectReminderUser.user_id' => $this->Session->read('Auth.User.id'),
'Project.project_status_id' => PROJECT_STATUS_OPEN,
),
'order' => 'Project.due_date',
)
);
$this->set('myTasks', $this->paginate('ProjectReminderUser'));
and the result look like this
array(
'ProjectReminderUser' => array(
'id' => '96',
'user_id' => '1',
'project_id' => '46'
),
'Project' => array(
'id' => '46',
'project_type_id' => '9',
'contact_id' => null,
'company_id' => null,
'subject' => 'Test Modified Field',
'description' => 'Test Modified Field',
'ProjectFile' => array(
(int) 0 => array(
'id' => '19',
'project_id' => '46',
'user_id' => '6',
'file_path' => '46_bhbinary_xmm_1728.jpg',
'notes' => null,
'created' => '2013-11-26 18:37:49'
),
),
'ProjectComment' => array(
)
),
'User' => array(
'password' => '*****',
'id' => '1',
'group_id' => '1',
'email' => 'xxx#xxxxx.com',
'first_name' => 'xxxx',
'deleted' => false,
'displayName' => 'xxxxx'
)
)
In the result There is data for Project.project_type_id, but I would like to have more detail of that. So I can show it as name instead of number. maybe like ProjectType.name instead.
How can I achieve this, so I can sort it in the view? something like this
$this->Paginator->sort('ProjectType.name', 'Type');
The problem is that Paginator doesn't play nice with deep model associations. I think though if rather than using Cake's methods for doing model associations, you instead do your joins manually, you may be able to work out the sorting as you want. See the below discussion.
http://sinkpoint.railsplayground.net/cakephp-pagination-deep-sort-and-habtm/
Worst comes to worse, you may have to also rewrite the model's paginate function to deal with sorting how you need it to.
How about
'contain' => array(
'Project' => array(
'ProjectComment',
'ProjectFile',
'ProjectType',
),
'User'
),
Looks like you did not contain "ProjectType"