Indirect modification of overloaded element of Illuminate\Support\Collection has no effect - database

im quite new in laravel framework, and im from codeigniter.
I would like to add new key and value from database
static function m_get_promotion_banner(){
$query = DB::table("promotion_banner")
->select('promotion_banner_id','promotion_link','about_promotion')
->where('promotion_active','1')
->get();
if($query != null){
foreach ($query as $key => $row){
$query[$key]['promotion_image'] = URL::to('home/image/banner/'.$row['promotion_banner_id']);
}
}
return $query;
}
that code was just changed from codeigniter to laravel, since in codeigniter there are no problem in passing a new key and value in foreach statement
but when i tried it in laravel i got this following error :
Indirect modification of overloaded element of Illuminate\Support\Collection has no effect
at HandleExceptions->handleError(8, 'Indirect modification of overloaded element of Illuminate\Support\Collection has no effect', 'C:\xampp\htdocs\laravel-site\application\app\models\main\Main_home_m.php', 653, array('query' => object(Collection), 'row' => array('promotion_banner_id' => 1, 'promotion_link' => 'http://localhost/deal/home/voucher', 'about_promotion' => ''), 'key' => 0))
please guide me how to fix this
thank you (:

The result of a Laravel query will always be a Collection. To add a property to all the objects in this collection, you can use the map function.
$query = $query->map(function ($object) {
// Add the new property
$object->promotion_image = URL::to('home/image/banner/' . $object->promotion_banner_id);
// Return the new object
return $object;
});
Also, you can get and set the properties using actual object properties and not array keys. This makes the code much more readable in my opinion.

For others who needs a solution you can use jsonserialize method to modify the collection.
Such as:
$data = $data->jsonserialize();
//do your changes here now.

The problem is the get is returning a collection of stdObject
Instead of adding the new field to the result of your query, modify the model of what you are returning.
So, assuming you have a PromotionBanner.php model file in your app directory, edit it and then add these 2 blocks of code:
protected $appends = array('promotionImage');
here you just added the custom field. Now you tell the model how to fill it:
public function getPromotionImageAttribute() {
return (url('home/image/banner/'.$this->promotion_banner_id));
}
Now, you get your banners through your model:
static function m_get_promotion_banner(){
return \App\PromotionBanner::where('promotion_active','1')->get();
}
Now you can access your promotionImage propierty in your result
P.D:
In the case you are NOT using a model... Well, just create the file app\PromotionImage.php:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class PromotionImage extends Model
{
protected $appends = array('imageAttribute');
protected $table = 'promotion_banner';
public function getPromotionImageAttribute() {
return (url('home/image/banner/'.$this->promotion_banner_id));
}
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'promotion_banner_id','promotion_link','about_promotion','promotion_active'
];

just improving, in case you need to pass data inside the query
$url = 'home/image/banner/';
$query = $query->map(function ($object) use ($url) {
// Add the new property
$object->promotion_image = URL::to( $url . $object->promotion_banner_id);
// Return the new object
return $object;
});

I've been struggling with this all evening, and I'm still not sure what my problem is.
I've used ->get() to actually execute the query, and I've tried by ->toArray() and ->jsonserialize() on the data and it didn't fix the problem.
In the end, the work-around I found was this:
$task = Tasks::where("user_id", $userId)->first()->toArray();
$task = json_decode(json_encode($task), true);
$task["foo"] = "bar";
Using json_encode and then json_decode on it again freed it up from whatever was keeping me from editing it.
That's a hacky work-around at best, but if anyone else just needs to push past this problem and get on with their work, this might solve the problem for you.

Related

db query in codeigniter active record returing object

I'm trying to pull a column out of the database, simple enough right? I'm using codeigniter's active record.
My Model Function
public function getcolumn($field, $table, $kfield, $key)
{
$this->db->select($field);
$this->db->from($table);
$this->db->where($kfield, $key);
$query = $this->db->get();
$results = $query->result();
return $results;
}
My Controller has:
public function users()
{
$body['handle'] = $this->admin->getcolumn('handle', 'users', 'userid', $userid)
$this->load->view('template/header');
$this->load->view('admin/users', $body);
$this->load->view('template/footer');
}
now when I print_r that variable in my view I get "Array ( [0] => stdClass Object ( [handle] => Zanigade ) ) "
Since I'm trying to use this function as a global "grab and go" function without writing a ton of functions, why won't it just return the name? What am I doing wrong? I've been playing with the output for 3 hours and I know this is a stupid easy fix and I'm just missing the mark.
Any help will be appreciated.
Put it all together using the "chaining" capability like so
$results = this->db->get()->row()->$field;
We get() one row() which (should) contain a field named $field.
It seems you are returning the result instead of single row, try this
public function getcolumn($field, $table, $kfield, $key)
{
$this->db->select($field);
$this->db->from($table);
$this->db->where($kfield, $key);
$query = $this->db->get();
return $query->row()->$field;
}
For More Information, Check the codeigniter user guide
https://www.codeigniter.com/userguide3/database/examples.html

Cakephp How to set find() to return blank array instead of empty array when no result matched

By default , cakephp would return empty array on find() when nothing founded.
but how to set it to show as blank array.
For example:
$customer = $this->Transaction->Customer->find(--conditions to return 0 result.--)
I want it to show as blank array like this.
array('Customer' => array('customer_id'=>null, 'name'=>null, 'lastname'=>null))
not just empty one like
array() or null
because I always got error shown in view that $customer['Customer']['name'] is undefined index. and I don't like to use isset() or is_null() to check before every time.
Use the afterFind callback method in your model. Something like this:
public function afterFind($results, $primary = false) {
if (empty($results)) {
$results = array('Customer' => array('customer_id'=>null, 'name'=>null, 'lastname'=>null))
}
return $results;
}
http://book.cakephp.org/2.0/en/models/callback-methods.html
If you really want/need to do this, you can use something like:
$default = array('Customer' => array('customer_id' => null, 'name'=>null, 'lastname' => null));
$customer = $this->Transaction->Customer->find(...)
$customer = array_merge($default, $customer);
This way, if the result is empty, it will use your default values.
However, this is not a good practice, because you might end up displaying "Welcome, NULL", in the page. You should use if (!empty($customer)) ... in your view.
Also, in this example, are you using find->('first') ?

access zf2 database result object in controller

How can I loop trough my db results in the controller by using a foreach loop?
$select = new Select();
$select->from('table_name');
$select->where(array('salt' => $salt));
$select->where(array('ip' => $this->_getUserIp()));
$rowset = $this->tableGateway->selectWith($select);
return $rowset;
I guess I need to convert the db result object to an array?
Thanks in advance
http://framework.zend.com/manual/2.1/en/modules/zend.db.result-set.html
Zend\Db\ResultSet\ResultSet extends traversable and therefore you can use foreach on it.
foreach($this->getSomeTable()->fetchAll() as $row) {
//here you can access the row as an array or use getters if you have set a prototype object
//eg
$userId = $row['user_id'];
$userId = $row->user_id;
$userId = $row->getId();
}
Also, I suggest reading through the getting started guide. All this basic stuff is explained there.
http://framework.zend.com/manual/2.1/en/user-guide/overview.html

drupal_write_record doesn't take object

In drupal 6 i used to do something like this:
<?php
/*
* CLASS Example
*/
class example {
var $id = NULL;
var $title;
var $body;
.....
// Save
function save() {
$primary_key = ($this->id == NULL ? NULL : 'id');
if (drupal_write_record('mytabble', $this, $primary_key)) {
return TRUE;
} else {
return FALSE;
}
}
}
?>
This worked quite well. But in Drupal 7, the drupal_write_record only takes an array and no longer the object $this. The new db_merge also only takes an array.
Since i want to save the properties of my object to the database, the above code was very handy and generic for all kinds of classes.
Is there an alternative way to write an object to database, or a method to place objectproperties into a an array?
Any help will be appreciated!
Robert
drupal_write_record does take an object or an array. Guess your problem is caused somewhere else.
drupal_write_record($table, &$record, $primary_keys = array())
$record: An object or array representing the record to write, passed in by reference. If inserting a new record, values not provided in $record will be populated in $record and in the database with the default values from the schema, as well as a single serial (auto-increment) field (if present). If updating an existing record, only provided values are updated in the database, and $record is not modified.
More info on drupal_write_record for D7.

Yii - How to get a values array from an Active Record

Using Yii, how can I get an array from an Active Record.
Say something like this:
array('foo', 'bar', 'lala')
From something like this:
MyTable::model()->findall()
If i understand you correctly:
$users = User::model()->findAll();
$usersArr = CHtml::listData( $users, 'id' , 'name');
print_r( $usersArr );
It will give you array id => name
Array {
2 => 'someone',
20 => 'kitty',
102 => 'Marian',
// ...
}
For yii2 , use:
yii\helpers\ArrayHelper::map(MyModel::find()->all(), 'id', 'name'));
or
yii\helpers\ArrayHelper::getColumn(MyModel::find()->all(), 'name'));
ActiveRecord class has an attribute called attributes. You can find its description here: http://www.yiiframework.com/doc/api/1.1/CActiveRecord#attributes-detail.
In order to get all attributes in an array, use this: $var = $model->attributes;
You could also do something like
$countries = Country::model()->findAll();
array_values(CHtml::listData($countries, 'country_id', 'country_name'));
which returns an array of all country names, or
array_keys(CHtml::listData($countries, 'country_id', 'country_name'));
which returns an array of all country ids.
How about:
Yii::app()->db->createCommand()
->setFetchMode(PDO::FETCH_COLUMN,0)
->select("mycolumn")
->from(MyModel::model()->tableSchema->name)
->queryAll();
The result would be:
array('foo', 'bar', 'lala')
Use the Yii2 ArrayHelper by including to your controller this will convert a model data to an associated array
use yii\helpers\ArrayHelper;
$post = ArrayHelper::toArray(ClientProfilesForm::findOne(['id' => 1]));
//or use it directly by
$post = yii\helpers\ArrayHelper::toArray(ClientProfilesForm::findOne(['id' => 1]));
Don't use ActiveRecord. Use CDBCommand->queryColumn()
Use Chtml to this is a Ugly Hack! Apply this solution is the better way to this that I found:
public function queryAll($condition = '', $params = array())
{
$criteria = $this->getCommandBuilder()->createCriteria($condition, $params);
$this->applyScopes($criteria);
$command = $this->getCommandBuilder()->createFindCommand($this->getTableSchema(), $criteria);
$results = $command->queryAll();
return $results;
}
You can add this code to an ActiveRecord class, e.g.:
class ActiveRecord extends CActiveRecord {
//...
}
And, use this way:
return $model->queryAll($criteria);
You can read more about in this link.
if you are using Yii1.1 and you need to get ALL data from AR as array you need to care about that it self. Yii1.1 AR doesn't have this feature out of the box
In Yii2 AR has asArray() method, it's very helpful
I hope my answer helps someone
Model::find()->select('id')->column();
Will return array of IDs.

Resources