Yii2 using ArrayHelper with another database - database

I am working on Yii2. I am using mysql and mssql databases. The mssql is on a remote site and I am able to access it. Now I am trying to add a dropdown list.
Controller
public function actionCreate()
{
$model = new AllowArea();
$sds = Yii::$app->sds->createCommand("Select * from Area")->queryAll();// mssql Database
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
'sds' => $sds
]);
}
View
<?= $form->field($model, 'salesman_code')->dropDownList(\common\models\AllowArea::toArrayList(), ['prompt' => 'Select a Booker']) ?>
Model
In my model, I have a function
public static function toArrayList(){
$sds = Yii::$app->sds->createCommand("Select * from Salesmen")->queryAll();
return ArrayHelper::map($sds::find()->all(),'SalesmanCode',function($sds, $defaultValue){
return $sds['SalesmanCode'].' - '.$sds['SalesmanNameFull'];
});
}
Previously I was using self in place of $sds. With $sds I am getting error
Class name must be a valid object or a string
Any help would be highly appreciated

You are not using Model/Class. So, in ArrayHelper
return ArrayHelper::map($sds, 'SalesmanCode', function($sds) {
return $sds['SalesmanCode'].' - '.$sds['SalesmanNameFull'];
});

Related

CakePHP Query Builder 4.x for SQL INSERT INTO IF NOT EXISTS

This CakePHP Query isn't using the conditional, $subQuery for some reason:
$subQuery = $this->queryFactory->newSelect('table_name')
->select(['id'])
->where(['id' => $id]);
$query = $this->queryFactory->newQuery()
->insert(
['id', 'machine', 'logfile', 'updated', 'time']
)
->into('table_name')
->values([
'id' => $id,
'machine' => $machine['id'],
'logfile' => $logFile,
'updated' => $updateDate,
'time' => $updateTime
])
->where(function (QueryExpression $exp) use ($subQuery) {
return $exp->notExists($subQuery);
});
$query->execute();
...it just inserts record even when it exists, but why?
The above code is only part of the required SQL that looks like this:
IF NOT EXISTS(
SELECT 1
FROM table_name
WHERE id = '$id'
)
INSERT INTO table_name (id, machine, logfile, updated, time)
VALUES (?,?,?,?,?)
ELSE
UPDATE table_name
SET updated = '$var1', time = ' $var2'
WHERE id = '$id';
There is no API that would allow to generate such a statement directly, the query builder isn't ment to generate (and execute) such SQL constructs, it can only compile SELECT, INSERT, UPDATE, and DELETE queries, and while the query expression builder can be used to stitch together arbitrary expressions, it will wrap itself and query objects into parentheses (as it is meant for use in query objects), which would be incompatible with what you're trying to build.
So if you want to run such constructs on SQL level, then you either have to write the SQL manually, or create custom expression classes that can build such constructs. In any case you would have to run the SQL manually then.
Here's a very basic quick & dirty example of such a custom expression class:
namespace App\Database\Expression;
use Cake\Database\ExpressionInterface;
use Cake\Database\ValueBinder;
use Closure;
class IfElseExpression implements ExpressionInterface
{
protected $_if;
protected $_then;
protected $_else;
public function if(ExpressionInterface $expression)
{
$this->_if = $expression;
return $this;
}
public function then(ExpressionInterface $expression)
{
$this->_then = $expression;
return $this;
}
public function else(ExpressionInterface $expression)
{
$this->_else = $expression;
return $this;
}
public function sql(ValueBinder $binder): string
{
$if = $this->_if->sql($binder);
$then = $this->_then->sql($binder);
$else = $this->_else->sql($binder);
return "IF $if $then ELSE $else";
}
public function traverse(Closure $callback)
{
$callback($this->_if);
$this->_if->traverse($callback);
$callback($this->_then);
$this->_then->traverse($callback);
$callback($this->_else);
$this->_else->traverse($callback);
return $this;
}
public function __clone()
{
$this->_if = clone $this->_if;
$this->_then = clone $this->_then;
$this->_else = clone $this->_else;
}
}
It could then be used something like this:
$notExists = (new \Cake\Database\Expression\QueryExpression())
->notExists($subQuery);
$insertQuery = $this->queryFactory->newQuery()
->insert(/* ... */)
//...
;
$updateQuery = $this->queryFactory->newQuery()
->update(/* ... */)
//...
;
$ifElse = (new \App\Database\Expression\IfElseExpression())
->if($notExists)
->then($insertQuery)
->else($updateQuery);
$binder = new \Cake\Database\ValueBinder();
$sql = $ifElse->sql($binder);
$statement = $connection->prepare($sql);
$binder->attachTo($statement);
$statement->execute();
See also
Cookbook > Database Access & ORM > Database Basics > Interacting with Statements
Yes, thanks. My own preference is to avoid the requirement to code the value binding explicitly. Using where(), I can do something like this:
$subQuery = $this->queryFactory->newSelect('table_name')
->select(['id'])
->where(['id' => $id])
->limit(1);
$find = $subQuery->execute()->fetchAll('assoc');
if (!empty($find)) {
$values = [
'id' => $id,
'machine' => $machine,
'logfile' => $logFile,
'updated' => $var1,
'time' => $var2
];
$query = $this->queryFactory->newInsert('table_name', $values);
} else {
$query = $this->queryFactory->newUpdate('table_name')
->set([
'updated' => $someVar,
'time' => $someVar2
])
->where(['id' => $id]);
}
$query->execute();

Jessneggers / Laravel MongoDB whereRaw lookup not working

I migrated my database from Sql Server to MongoDB
I want to Join existing customer Table with contact Table .
Customer have multiple contacts . I tried whereRaw lookup
customer collection
{
"_id": 77,
"custid": 93
}
Contact Collection
{"_id":77,"contactid":77,"custid":93,"firstname":"Christy ","lastname":"Lambright" }
{"_id":79,"contactid":79, "custid":93,"firstname":"Marlys ","lastname":"Barry" }
Customer Modal
class custt extends Model
{
use Notifiable;
protected $primaryKey = 'id';
}
Contact Modal
class contact extends Model
{
use Notifiable;
protected $primaryKey = 'id';
In Controller
$cnt = DB::collection("custts")->raw(function($collection)
{
$more_where = [];
$more_where[]['$lookup'] = array(
'from' => 'contacts',
'localField' => 'custid',
'foreignField' => 'custid',
'as' => 'country',
);
return $collection->aggregate($more_where);
});
Error comes --
Empty Results
I tried Lots of options for hasMany and belongstoMany . Not working ...
please suggest
ok , finally found it working
source - https://github.com/jenssegers/laravel-mongodb/issues/841
$cnt = custt::raw(function($collection)
{
return $collection->aggregate(
[[
'$lookup' => [
'as'=>'info',
'from'=>'contacts',
'foreignField'=>'custid',
'localField'=>'custid'
]
]]
);
});

save mathod in database cause Array to string conversion error in laravel

when I execute custom command with
php artisan query:all
every thing is good except error shown in console the error is
Array to string conversion
and the data is stored to database I did not understand the cause of this error and it's hidden when hide save to database method
the code of my service which the problem cause inside it is
<?php
namespace App\Services;
use Carbon\Carbon;
use GuzzleHttp\Client;
use App\Models\weatherStatus;
use Illuminate\Support\Collection;
class ApixuService
{
public function query(string $apiKey, Collection $cities): Collection
{
$result = collect();
$guzzleClient = new Client([ //create quzzle Client
'base_uri' => 'http://api.weatherstack.com'
]);
foreach ($cities as $city) {
$response = $guzzleClient->get('current', [
'query' => [
'access_key' => $apiKey,
'query' => $city->name,
]
]);
$response = json_decode($response->getBody()->getContents(), true); //create json from $response
$status = new weatherStatus(); //create weatherStatus object
//adding prameters
$status->city()->associate($city);
$status->temp_celsius = $response['current']['temperature'];
$status->status = $response['current']['weather_descriptions'];
$status->last_update = Carbon::createFromTimestamp($response['location']['localtime_epoch']);
$status->provider = 'weatherstack.com';
//save prameters
$status->save();
$result->push($status);
}
return $result;
}
}
So you can find some clarity in what you are trying to save, do the following:
$response = json_decode($response->getBody()->getContents(), true);
dd($response);
dd() will dump all the data from the $response and exist the script.
One of the values you are trying to save is an array. The field you are trying to save accepts a string and not array.

Update records of database table : Laravel

I need to update the database table according to the edited data.
controller
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->update($request->all());
return back();
}
But nothing happens when I submit the form. When I use dd($request->all()); at the beginning of the function, it correctly shows the edited data as follows.
array:10 [▼
"_method" => "patch"
"_token" => "gOCL4dK6TfIgs75wV87RdHpFZkD7rBpaJBxJbLHF"
"editname" => "SUP_EVA_001"
"editdesc" => "des"
"editprice" => "1000.050"
"editlimit" => "1"
"editperunit" => "20.000"
"editexceedunit" => "30.000"
"productid" => "1"
"id" => "1"
]
But database has not been updated.
My table name is Table: subscription_plans and model is SubscriptionPlan
These are the table columns:
protected $fillable = [
'name',
'description',
'price',
'usage_limit',
'charge_per_unit',
'charge_per_unit_exceed',
'is_limit_exceed_considered',
'product_id'
];
Any idea on how to solve it or what I have done wrong?
If your solution did not work, try the 1by1 like this.
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->_method = $request->_method;
$subscriptionplan->_token = $request->_token;
$subscriptionplan->editname = $request->editname;
$subscriptionplan->editdesc = $request->editdesc;
$subscriptionplan->editprice = $request->editprice;
$subscriptionplan->editlimit = $request->editlimit;
$subscriptionplan->editperunit = $request->editperunit;
$subscriptionplan->editexceedunit = $request->editexceedunit;
$subscriptionplan->productid = $request->productid;
$subscriptionplan->save();
return back();
}
In order for Laravel to automatically fill the model attributes, the indexes of the array passed to the fill method must correspond to your model attributes names.
Also, instead of
$subscriptionplan->update($request->all());
Use
$subscriptionplan->fill($request->all());
Then save the subscription plan with $subscriptionplan->save();

Yii record is not inserting into DB

Below is my controller & model logic - I just started a barebones Yii installation to play around with it more.
I get no errors but don't see the new entry in the database - my db has been configured in the main.php (this works as Gii runs).
// controllers/PageController.php
class PageController extends Controller
{
public function actionSave($value='')
{
$pageObj = new Page;
$pageObj->savePage();
}
}
// models/Page.php
class Page extends CActiveRecord
{
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'page';
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('title, date_updated', 'required'),
array('live', 'numerical', 'integerOnly'=>true),
array('user_id', 'length', 'max'=>10),
array('title', 'length', 'max'=>100),
array('content, date_published', 'safe'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, user_id, live, title, content, date_updated, date_published', 'safe', 'on'=>'search'),
);
}
/**
* #return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'comments' => array(self::HAS_MANY, 'Comment', 'page_id'),
'user' => array(self::BELONGS_TO, 'User', 'user_id'),
'files' => array(self::MANY_MANY, 'File', 'page_has_file(page_id, file_id)'),
);
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'user_id' => 'User',
'live' => 'Live',
'title' => 'Title',
'content' => 'Content',
'date_updated' => 'Date Updated',
'date_published' => 'Date Published',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
*
* Typical usecase:
* - Initialize the model fields with values from filter form.
* - Execute this method to get CActiveDataProvider instance which will filter
* models according to data in model fields.
* - Pass data provider to CGridView, CListView or any similar widget.
*
* #return CActiveDataProvider the data provider that can return the models
* based on the search/filter conditions.
*/
public function search()
{
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id,true);
$criteria->compare('user_id',$this->user_id,true);
$criteria->compare('live',$this->live);
$criteria->compare('title',$this->title,true);
$criteria->compare('content',$this->content,true);
$criteria->compare('date_updated',$this->date_updated,true);
$criteria->compare('date_published',$this->date_published,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
/**
* Returns the static model of the specified AR class.
* Please note that you should have this exact method in all your CActiveRecord descendants!
* #param string $className active record class name.
* #return Page the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function savePage($value='')
{
$page = new page;
$model->isNewRecord = true;
$model->primaryKey = NULL;
$page->title='sample page';
$page->content='content for the sample page';
$page->save(false);
}
}
In Yii, when you want to insert into a table which has some null columns, you must put null columns in your rules as SAFE like below:
array('primaryKey','safe'),
Now, Yii knows that primaryKey is a null column. So, there would be no problem via inserting into the current model.
As a note, when you call save() method with FALSE, you are telling to your model to do not the validation on insert.
Also, the correct way to skip possible errors is to validate your model before inserting like below:
if($model->validate()){
// VALIDATE, YOU CAN CALL SAVE FUNCTION
}else{
//here you can send an error message via FLASH or you can debug what the exact error is like below:
CVarDumper::dump($model->getErrors(),5678,true);
Yii::app()->end();
}
I hope, it help
So simple... I hate Yii sometimes :-)
Had to set the save() to save(false)
$page = new page;
$page->isNewRecord = true;
$page->primaryKey = NULL;
$page->title='sample page';
$page->content='content for the sample page';
$page->save(false);
Thanks for that - I had missed out some columns.. (silly me)
Improve the function even further with the help above..
public function savePage()
{
$page = new page;
$page->isNewRecord = true;
$page->primaryKey = NULL;
$page->user_id = 1;
$page->live = 0;
$page->content='content for the sample page';
$page->date_updated = date('Y-m-d H:i:s');
$page->date_published = date('Y-m-d H:i:s');
$page->title='sample page';
if ($page->validate()) {
$page->save();
} else {
CVarDumper::dump($page->getErrors(),5678,true);
Yii::app()->end();
}
}

Resources