phql changed when executing using modelsManager - phalcon

I'm new to Phalcon and would like to create a PHP web-service on my WAMP server. I have a table called "coreswings" in MySQL database and it represents the cores and wings of a large building. There are five fields: abbr, name, type, busyFrom, busyTo.
Following the tutorial on http://docs.phalconphp.com/en/latest/reference/tutorial-rest.html , I can route my requests to my desired functions, but the phql, "SELECT * FROM coreswings", doesn't work and returns me fatal errors.
index.php
<?php
/*###########################################################################
########## Set up connection to be used by model CoresWings, start ##########
###########################################################################*/
// use Loader() to autoload the model
$loader = new \Phalcon\Loader();
$loader->registerDirs(array(__DIR__.'/models/'))->register();
$di = new \Phalcon\DI\FactoryDefault();
// set up the database service
$di->set('db', function(){
return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
"host" => "localhost",
"username" => "user",
"password" => "user_pw",
"dbname" => "map"
));
});
// create and bind the DI to the application
$app = new \Phalcon\Mvc\Micro($di);
/*#########################################################################
########## Set up connection to be used by model CoresWings, end ##########
#########################################################################*/
/*#########################################################
########## create routes according to api, start ##########
#########################################################*/
// get all cores and wings
$app->get('/coresWings', function() use ($app){
$phql = "SELECT * FROM coreswings";
$coresWings = $app->modelsManager->executeQuery($phql);
$data = array();
foreach($coresWings as $coreWing){
$data[] = array(
'abbr' => $coreWing->abbr,
'name' => $coreWing->name,
'type' => $coreWing->type,
'busyFrom' => $coreWing->busyFrom,
'busyTo' => $coreWing->busyTo,
);
}
echo json_encode($data);
});
// testing purpose
$app->get('/testing', function(){
$data = array(
'function' => 'tesing',
'data' => '001'
);
echo json_encode($data);
});
/*#######################################################
########## create routes according to api, end ##########
#######################################################*/
$app->handle();
?>
When I access the URL http://localhost/FYP/001/api/coresWings, the following errors are shown:
( ! ) Fatal error: Uncaught exception 'Phalcon\Mvc\Model\Exception' with message 'Table "cores_wings"
doesn't exist on database when dumping meta-data for CoresWings' in
D:\Program Files\wamp\www\FYP\001\api\index.php on line 39
( ! ) Phalcon\Mvc\Model\Exception: Table "cores_wings" doesn't exist on database when dumping meta-data for CoresWings in D:\Program Files\wamp\www\FYP\001\api\index.php on line 39
Of course I don't have a table called "cores_wings", but my phql is "SELECT * FROM coreswings". Please tell me if I have done anything wrong. Thanks so much.
#
mysql> describe coreswings;
+----------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------------+------+-----+---------+-------+
| abbr | varchar(63) | NO | PRI | NULL | |
| name | varchar(1024) | YES | | NULL | |
| type | enum('core','wing') | NO | | NULL | |
| busyFrom | time | YES | | NULL | |
| busyTo | time | YES | | NULL | |
+----------+---------------------+------+-----+---------+-------+
Model: CoresWings.php
use Phalcon\Mvc\Model,
Phalcon\Mvc\Model\Message,
Phalcon\Mvc\Model\Validator\InclusionIn,
Phalcon\Mvc\Model\Validator\Uniqueness;
class CoresWings extends Model{
public function validation(){
// building type must be "core" or "wing"
$this->validate(new InclusionIn(
array(
"field" => "type",
"domain" => array("core", "wing")
)
));
// building abbreviation must be unique
$this->validate(new Uniqueness(
array(
"field" => "abbr",
"message" => "Abbreviation of a building must be unique"
)
));
// check if any messages have been produced
if($this->validationHasFailed()==true){
return false;
}
}
}
?>

If you want minimal configuration then you should follow some PhalconPHP's conventions.
One of them is that it for CamelCaseModel PhalconPHP uses camel_case table.
If you want to set different tabel for model then you should set it's source:
class CoresWings extends Model{
public function initialize() {
$this->setSource('coreswings');
}
}

You can use Phalcon\Mvc\Model::getSource() method. It is table name map with manual.

Related

TypeScript Sequelize : How to join two tables with common

There are three tables.
Tables :
Trip
id | start_destination_id | end_destination_id | arrive_time |
-------------------------------------------------------------------
1 | S | E | 09:00 |
Destination
id | name
---------
S | Start
E | End
Schedule
id | start_destination_id | end_destination_id | should_arrive |
-------------------------------------------------------------------
1 | S | E | 08:00 |
2 | A | E | 10:00 |
Query
SELECT
Trip.*,
Schedule.should_arrive
FROM
Trip
LEFT JOIN
Schedule
ON
Trip.start_destination_id = Schedule.start_destination_id
AND
Trip.end_destination_id = Schedule.end_destination_id
I am trying to include Schedule in Trip.findAll but receive error
Exception: SequelizeEagerLoadingError: Schedule is not associated to Trip!
Is there a way that I can join them together without using foreign keys and raw queries?
Many thanks.
Finally I found a solution (not sure if it is a hack).
Schedule.ts
// add these lines
...
#ForeignKey(() => Trip)
#Column({ type: DataType.VIRTUAL })
private _dummyForTrip: undefined;
...
Then create an association between Schedule and Trip.
Trip.ts
#HasMany(() => Schedule)
public schedules: Schedule[] | null
Then you can include Schedule inside Trip by using include.on
const trips = await Trip.findAll({
include: [{
model: Schedule,
on: {
'$schedules.start$': { [Op.col]: "Trip.start_destination" },
'$schedules.end$': { [Op.col]: "Trip.end_destination" },
}
}],
where: {
id: { [Op.in]: payload.inputTripIdArr }
}
});

Yii: CGridView Columns Totals

Please help!
I need to total three columns (Budget, Release and Expenditure) under header in CGridView as shown below
| Fund | Budget | Release | Expenditure|
| | Total:30 | Total:15 | Total: 8 |
| A | 10 | 5 | 3 |
| B | 20 | 10 | 5 |
You can achieve that by inheriting CGridView and overriding the renderTableHeader function.
1st. Make your grid:
<?php
Yii::import('zii.widgets.grid.CGridView');
class CGridViewWithTotals extends CGridView
{
public function renderTableHeader()
{
if(!$this->hideHeader)
{
echo "<thead>\n";
if($this->filterPosition===self::FILTER_POS_HEADER)
$this->renderFilter();
echo "<tr>\n";
foreach($this->columns as $column)
$column->renderHeaderCell();
echo "</tr>\n";
if($this->filterPosition===self::FILTER_POS_BODY)
$this->renderFilter();
if($this->getHasFooter())
{
echo "<tr>\n";
foreach($this->columns as $column)
$column->renderFooterCell();
echo "</tr>\n";
}
echo "</thead>\n";
}
else if($this->filter!==null && ($this->filterPosition===self::FILTER_POS_HEADER || $this->filterPosition===self::FILTER_POS_BODY))
{
echo "<thead>\n";
$this->renderFilter();
echo "</thead>\n";
}
}
}
To prevent footer from rendering(if you dont need it), override CGridView::renderTableFooter()
2nd. Use your new grid as always:
<?php
$this->widget('CGridViewWithTotals', array(
'id'=>'my-grid',
'dataProvider'=>$model->search(),
'emptyText'=>'No items found.',
'ajaxUpdate'=>false,
'columns'=>array(
array(
'name'=>'field1',
'footer'=>$total,
),
),
));
?>

how to check, if authenticated user in array from db

In my DB I have a project table which has
project
id | title | users |
1 | First | 1,2,3 |
2 | Second| 2,6 |
how can I check Yii::app()->user->id contained in users field? I want to check, if true then show row in gridview.
Which $criteria must I use?
Use LIKE query for checking your user id exist or not in users column.
$user = Yii::app()->user->id;
$result = Yii::app()->db->createCommand('SELECT * FROM project WHERE users LIKE "%'.$user.'%"')->queryAll();
if(count($result)){
//Your other scripts to show in grid view
}
If you have a Project model class then you also can use:
$user = Yii::app()->user->id;
$criteria = new CDbCriteria;
$criteria->select = '*';
$criteria->compare('t.users', $user, true);
$results = Project::model()->findAll($criteria);

Simple relation in YII, can't get it done

This is the first time I use relations in Yii, the question is very simple.
MODULE TABLE
name - PK
status - FK status_id
STATUS TABLE
id PK
name
So, each Module HAS one status.
But I can not seem to get it working.
Module.php (Model)
public function relations()
{
return array(
'status'=>array(self::BELONGS_TO, 'ModuleStatus', 'status'),
);
}
I access them this way:
$modulesAR = Module::model()->with('status')->findAll();
if( $modulesAR )
{
foreach( $modulesAR as $moduleAR )
{
$this->modules[ $moduleAR->name ] = array(
'sessionLimit' => isset($moduleAR->sessionLimit) ? $moduleAR->sessionLimit : 0,
'status' => isset($moduleAR->status) ? $moduleAR->status : 'disabled',
);
}
}
Var_dump(Yii::app()->module->modules;
array(3) {
["digidoc"]=>
array(2) {
["sessionLimit"]=>
int(0)
["status"]=>
string(1) "2" // Should say "Disabled"
}
["docusearch"]=>
array(2) {
["sessionLimit"]=>
int(0)
["status"]=>
string(1) "1" // Should say "Enabled"
}
["printbox"]=>
array(2) {
["sessionLimit"]=>
int(0)
["status"]=>
string(1) "2" // Should say "Disabled"
}
}
I will appreciate any help.
Thanks!
EDIT:
query executed by Yii:
SELECT `t`.`name` AS `t0_c0`, `t`.`status_id` AS `t0_c1`, `t`.`session_limit` AS `t0_c2`, `status`.`id` AS `t1_c0`, `status`.`name` AS `t1_c1` FROM `ss_module` `t` LEFT OUTER JOIN `ss_module_status` `status` ON (`status`.`id`=`t`.`name`)
+------------+-------+-------+-------+-------+
| t0_c0 | t0_c1 | t0_c2 | t1_c0 | t1_c1 |
+------------+-------+-------+-------+-------+
| digidoc | 2 | 0 | NULL | NULL |
| docusearch | 1 | 2 | NULL | NULL |
| printbox | 2 | 0 | NULL | NULL |
+------------+-------+-------+-------+-------+
EDIT 2:
Changing the last
ON (`status`.`id`=`t`.`name`);
to
ON (`status`.`id`=`t`.`status_id`);
works as expected, by I dont know how to fix it in Yii.
When you peek into $moduleAR->status, you get the whole Status model instance, not it's id. So just go on and peek into that instance:
$moduleAR->status->name.
That's what ActiveRecord magic is intended for ;)
And inversely, if you have Status model, you should have a relation there saying something like this:
'modules' => array(self::HAS_MANY, 'Module', 'status_id')
Which could make the following possible:
$status = Status::model()->find(/*somehow*/);
/* now that $status is an Status instance */
foreach ($status->modules as $module) {
// here you are! looping over all modules connected to this status
// each $module is a full-fledged Module instance
}

yii - create nested cgridview

Is it possible to create nested table using cgridview?
I'd like to have the final output as follows
| Transaction | Total |
| T-001 | $100 |
| Item | Price | // here is the nested table
| I-1 | $50 |
| I-2 | $50 |
| T-002 | $90 |
| Item | Price | // here is the nested table
| I-3 | $90 |
I know you can do this using a custom template, but i'd like a neater solution using a widget like CGRidView.
Thanks
If nested table is inside cell then you can, just create function in your model that will render table and return content. You can set third parameter of widget function to true to return content. If you want to enable pagination for nested table then be sure to manually set widget id and allow ajax update.
In model:
function getNestedTable() {
return Yii::app()->controller->widget(..., ..., true);
}
In columns definition use:
'columns' => array(
array(
'name' => 'nestedTable',
'type' => 'raw'
)
)
I think the best way to achieve what you want is to use custom functions in your CActiveRecord model (if you've a CActiveDataprovider for the grid), and put that 'nested table' as normal column:
| Transaction | Item | Price | Total |
------------------------------------------
| T-001 | I-1 | $50 | $100 |
| I-2 | $50 |
------------------------------------------
| T-002 | I-3 | $90 | $90 |
------------------------------------------
In your model you've to define get functions that return data in HTML with line breaks (for example with a br:
class Item extends CActiveRecord {
...
public function getIdItems()
{
$string = '';
foreach($this->items as $item) {
if ($string != '') $string .= '<br/>';
$string .= ' '.$item->textId; // 'I-3', 'I-2'...
}
return $string;
}
public function getPriceItems()
{
$string = '';
foreach($this->items as $item) {
if ($string != '') $string .= '<br/>';
$string .= ' '.$item->price; // $50, $90...
}
return $string;
}
...
}
And to show the new columns in your grid:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'anotacionesGrid',
'dataProvider'=>$dataProvider,
'columns'=>array(
'transaction',
'idItems:html:Item',
'priceItems:html:Price',
'total'
)
);