I am a newbie to yii and confused how to do this.
I am working on creating a webpage.
I have a model in Yii(model1). At some instance I want to save few selected values to another table. Hence forth I have created a new model for new table (say model2). I have this code in my controller and does'nt seem to work
if(isset($_POST['model1']['mobile']))
{
foreach ($_POST['model1']['mobile'] as $id)
{
$model2->email = $this->email;
$model2->save();
}
}
What I am trying to do here is, in my model1 I have many attributes out of which I want to save only 'email' attribute to the second table(model2). This is giving me an error as "Model1Controller.email" is not defined. Am I missing something here?
Your $this refers to class variable, not to foreach $id
if(isset($_POST['model1']['mobile']))
{
foreach ($_POST['model1']['mobile'] as $id)
{
$model2->email = $id->email;
$model2->save();
}
}
Related
I'm fetching data from database, inside foreach loop i have to add one array index list_array
$list = Lists::where('name',$request->name)->get();
$Data=[];
foreach($list as $key => $list_row)
{
$list_row['list_array'][]=$list_row['data_1'];
$list_row['list_array'][]=$list_row['data_2'];
$Data[]=$list_row;
}
It should be of array type but when i declare it as array it is not working,
message: "Indirect modification of overloaded property
App\Models\Lists
Any solution to create list_array as an array index inside foreach loop. Thanks
You are not dealing with an array, you are dealing with an App/Models/Lists model. What you probably instead want to do is adding a custom attribute to the model. This happens one step before.
// your model
class Lists
{
protected $appends = ['list_array'];
public function getListArrayAttribute()
{
$data = [
// your array data from where ever
];
return $data;
}
}
You then can access (without adding it when you want to access the data) the new attribute from within the model, like so:
// where you access your data
$lists = Lists::where('name', 'whatever')->get();
foreach($lists as $list) {
dd($lists->list_array)
}
You can read more about the so called Accessors here:
https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor (Laravel 8)
https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor (Laravel 9)
I hope I got the intention of your question right. From your question it's not very clear what data you want to add and where it is coming from. There might be other and better ways too.
Edit:
Based on the comment from #user3653474 the Accessor function could look like this.
public function getListArrayAttribute()
{
$data = [
$this->data_1,
$this->data_2,
];
return $data;
}
data_1 and data_2 are the column names in the table of the same model.
As you probably know, we can use refresh method on a model instance in order to refresh it from the database.
Refresh completely reloads all columns from database. refresh method does not seem to take any input, so I was wondering if there is a way to refresh some fields from the database.
To demonstrate, let's have a pseudo-model as below:
Foo
---
bar: char
baz: char
And I have a single instance of Foo called $foo. $foo->refresh() fetches both $foo->bar and $foo->baz. How do I only fetch/refresh bar field?
Thanks in advance.
Environment
PHP 7.4.5
Laravel 7.x
I think there's no way to do such. The best option you have is to get the PK of your $foo object and query for the fields you want:
$id = $foo->id;
$refreshed = Foo::select('bar')->where('id', '=', $id)->first();
$foo->bar = $refreshed->bar;
However, this will unsync your model with the database. Another option is to create a custom method in your model that does it in a more abstract way and retrieves the new unsynced object:
// In your model:
public function refreshField(string $field)
{
$this->$field = (new static())
->select($field)
->where($this->key(), '=', $this->{$this->key()})
->first()->$field;
return $this;
}
// Then outside:
$foo = Foo::first();
// perform actions. . .
$foo->refreshField('bar');
Again, keep in mind that this will keep your model unsynced with the database. Also, this is a POC, I didn't test it, but the general idea should work. If you create a parent model and extend all your other models from this (which extends from Eloquent), this should work with any of your models.
For a more complete version, you can pass an array instead of a string and retrieve all the fields that you want to refresh, then assign them in a loop:
public function refresFields(string ...$fields)
{
$fields = $this->$field = (new static())
->select($fields)
->where($this->key(), '=', $this->{$this->key()})
->first();
foreach ($fields as $field) {
$this->$field = $field;
}
return $this;
}
I wouldn't recommend this, but if you really need it, give it a try. Good luck
I am currently trying to make a function that calls different scopeQueries such as scopeByLocation() or scopeByPublished() on models defined in an array. I've got the basics working through [this link][1]. However, when trying to access custom made query scopes that are defined in the corresponding model, I get the following error: "Call to undefined method Illuminate\Database\Query\Builder::ForLocation($location)->get()".
What I want to achieve is a single method which loops through every model in the array of models and retrieves & calls the right scopeQuery on the model, something like this:
$modelElements = $model::{$queryScope}();
Where for example $model = 'Modules\News\Models\Article'
And $queryScope is a defined queryScope in the model itself. E.g. scopeForLocation($location).
I've tested $queryScope = 'all' and I get a result just fine, however when I try to access a custom queryScope ($queryScope = 'ForLocation($location)->get') that exists within for example the Location model, I get the following error: "Call to undefined method Illuminate\Database\Query\Builder::ForLocation($location)->get()".
So this all happens in a foreach-loop where every model in my models-array gets called and then the corresponding queryScope gets called on the model.
Why does the $queryScope = 'all' method works on my dynamic models, but other scopes throw an error? I really hope someone could help me get into the right direction with this issue.
Thanks in advance,
J. Doe.
Okay, I've finally solved it the following way:
//array of models
public function models()
{
return [
'Modules\Website\Models\Article',
...
];
}
//function that retrieves all elements for a model
public function getAllElementsForModel($model, $param)
{
//instantiate model
$model = new $model;
//call queryScope
//'queryScope' could be any queryScope that is defined within your model(s),
//the parameters are needed for the associated queryScope
$query = call_user_func_array([$model, 'queryScope'], [$param1, $param2]);
$result = $query->get();
//do stuff with your $result
}
//retrieves all
public function all($param)
{
//loop through the array of models
foreach($this->models() as $model){
$this->getAllElementsForModel($model, $param);
//do stuff here...
}
}
Sharing is caring!
this is the my first post and I'm really confused with the below code. I'm building a gaming website (my first project using yii) and I'm using afterSave() in the model to insert data to another table because the relation is Many to Many. I'm fetching data from database then exploding it to get numbers only (so I can insert it in the other table) instead of ('2','|','3'). The problem is foreach is inserting one row instead (despite the fact it should insert more than one row) of two in my example and the inserted con_id value is always 1, I don't understand the issue here, please help me.
protected function afterSave()
{
$model1 = new GameConsole();
$con[] = explode('|', $this->con_id);
foreach($con as $row) {
$model1->game_id = $this->game_id;
$model1->con_id = $row;
$model1->save(false);
}
parent::afterSave();
}
you are saving one model over and over
you should change your code like this:
protected function afterSave()
{
$con[]= explode('|', $this->con_id);
foreach($con as $row){
$model1=new GameConsole; // this line creates new GameConsole
$model1->game_id= $this->game_id;
$model1->con_id=$row;
$model1->save(false);
}
return parent::afterSave(); // update : return it
}
and btw why are you not validating?
This should return a list of about five locations. It returns nothing with no errors. I've tested the sql using mysql workbench. It returns the data just fine. Right now I'm writing the back end so I'm not concerned with using views or the dataprovider. I'm just making sure my back end functions work. So with that in mind, how would you return the data retrieved by findAllBySql?
class CashLogic
{
public function AllLocations()
{
$model = new Locations;
$allLocations = $model->findAllBySql("SELECT name from locations");
return $allLocations;
}
}
class SiteController extends Controller
{
public function actionIndex()
{
$model = new CashLogic;
$data = $model->AllLocations();
return $data;
}
}
The findAllBySql() method returns an array of models. From your code it seems you only want the names of locations. An alternative method is
$AllLocations=CHtml::listData(Locations::model()->findAll(),'name','name');
This will return an array of the form array('name'=>'name','name'=>'name'). A better solution would be to replace the first name with the primary key of your locations table.