My controller looks like this:
public function show($id)
{
$model = MyModel::with([
'model2.model3.model4:id,value',
...
]);
if (myCondition) {
unset($model->model2->model3->model4);
$model->model2->model3->model4 = Model4::where('value', 'Some Value')->first();
}
return $audit;
}
In certain condition I'd like to override the result from the query with another value from the Model4 to return the good data to the client.
But I want to know if there is another way with laravel to do that. Actually I have to use unset and then push the new content if I want to change the value of the model4 property. If I don't use unset the object isn't changed, the value new value assigned to model4 is ignored I don't know why I can't just write this line
$model->model2->model3->model4 = Model4::where('value', 'Some Value')->first();
So I want to know why I can't see changes in my json object when I don't use unset and I want to know if there is anotehr way to deal with laravel for my situation ?
You can simply use setRelation method.
if ($myCondition) {
$model->model2->model3->setRelation('model4', Model4::where(...)->first());
}
Related
I need a little help and I can’t find an answer. I would like to replicate a row from one data table to another. My code is:
public function getClone($id) {
$item = Post::find($id);
$clone = $item->replicate();
unset($clone['name'],$clone['price']);
$data = json_decode($clone, true);
Order::create($data);
$orders = Order::orderBy('price', 'asc')->paginate(5);
return redirect ('/orders')->with('success', 'Success');
}
and i got an error :
"Missing argument 1 for
App\Http\Controllers\OrdersController::getClone()"
.
I have two models: Post and Order. After trying to walk around and write something like this:
public function getClone(Post $id) {
...
}
I got another error
Method replicate does not exist.
Where‘s my mistake? What wrong have i done? Maybe i should use another function? Do i need any additional file or code snippet used for json_decode ?
First of all, make sure your controller gets the $id parameter - you can read more about how routing works in Laravel here: https://laravel.com/docs/5.4/routing
Route::get('getClone/{id}','YourController#getClone');
Then, call the URL that contains the ID, e.g.:
localhost:8000/getClone/5
If you want to create an Order object based on a Post object, the following code will do the trick:
public function getClone($id) {
// find post with given ID
$post = Post::findOrFail($id);
// get all Post attributes
$data = $post->attributesToArray();
// remove name and price attributes
$data = array_except($data, ['name', 'price']);
// create new Order based on Post's data
$order = Order::create($data);
return redirect ('/orders')->with('success', 'Success');
}
By writing
public function getClone(Post $id)
you are telling the script that this function needs a variable $id from class Post, so you can rewrite this code like this :
public function getClone(){
$id = new Post;
}
However, in your case this does not make any sence, because you need and integer, from which you can find the required model.
To make things correct, you should look at your routes, because the url that executes this function is not correct, for example, if you have defined a route like this :
Route::get('getClone/{id}','YourController#getClone');
then the Url you are looking for is something like this :
localhost:8000/getClone/5
So that "5" is the actual ID of the post, and if its correct, then Post::find($id) will return the post and you will be able to replicate it, if not, it will return null and you will not be able to do so.
$item = Post::find($id);
if(!$item){
abort(404)
}
Using this will make a 404 page not found error, meaning that the ID is incorrect.
I've a very big doubt about how works laravel for a very simple thing:
If I call:
$companies=User::All();
Then I can use statement like this in a forach:
foreach($companies as $company)
$company['new_field']= 'something';
If i'm limiting the output of the query like:
$companies = DB::table('companies')
->select('id','name','email','business_name',...)->get();
The things doesnt work as before,
I try with or without the ->get()
I try to convert with ->toArray() (errors rised)
I try with put() and push() for collections method and agains errors...
How can I add a field in every item of the collection just to pass it to a view?
Try like this, hope it works for you:
$users=User::select('id','name','email','business_name',...)->get()->toArray();
and then use foreach loop like this:
foreach($users as $key => $value ){
$users[$key]['newField'] = "Demo";
}
If you are using Laravel and model in it so there is a better way to add custom attribute or field here is what i do for custom field
For Example :
There is a Model Name User
so in User Model
add a property name appends like :
class User extends Model
{
protected $appends = ['new_field'];
public function getNewFieldAttribute() // defining field logic here
{
return // your code
}
So you no need to use foreach and looping and adding new field
for more have a look on laravel doc : https://laravel.com/docs/5.5/eloquent-mutators#accessors-and-mutators
Suggestion
you can limit your output with Model too.
User::select('id','name','email','business_name',...)->get();
if you are making an array like
User::select('id','name','email','business_name',...)->get()->toArray();
so this will also give you your custom field
I have a table with a field called vat_free. So my model was created with a property $vat_free. Its value can be 0 or 1.
I want my view to show No or Yes, instead of 0 or 1. I can do it creating a getter like getVatFree(), but it seems like a messy solution, because then I'll have two properties to the same field, even though it would serve different purposes.
So how can I use only the original property $vat_free? Couldn't I modify its getter?
Creating method
public function getVatFreeString(){
return $this->vat_free ? 'Yes':'No';
}
Is proper solution, it's not messy.
You could do like
$vat_free = YES or NO
but right before save this object you would override object class with beforeSave() method like following:
beforeSave(){
if($this->vat_free = YES){
$this->vat_free = 1
}else{
$this->vat_free = 0;
}
}
and override afterFind() to do the reverse(for beforeSave()) translate. But this is even messy and will not work if u do bulk save or retrieve.
I see 2 solutions.
Go with what you have said getVatFree(), this is whole purpose of OOP encapsulation.
Instead of making 1 or 0 in db, do Y or N values, you can use them in both places without problems.
In your model, create a new field that will be used for display purposes only.
class User extends CActiveRecord
{
public $displayVatFreeFlag;
public function rules() { ... }
public function afterFind()
{
$this->displayVatFreeFlag = ($this->vat_free ? 'Yes':'No');
}
}
Then, in your field, display the field as normal.
Vat free : <?php echo $model->displayVatFreeFlag; ?>
I am trying to print a variable fromm saveAction so i can see what is the value of that variable. I am learning Zend2 and i have continued where other developer stoped so i am trying to understand it better...This application is also using Doctrin.
I have this action which will save some data to database.
public function saveAction() {
$view = new ViewModel();
$logedUser = $this->getLogedUser();
print_r($_POST);
$shopId = (int) $this->params()->fromPost('shop_id', null);
print_r($shopId);
$shop = $this->getServiceLocator()
->get('Catalog\Model\Shop')
->getRepository()
->findOneBy(array('id' => $shopId, 'user' => $logedUser->getId()));
print_r($shop);
return $logedUser;
return $shop;
return $view;
}
I can print values from post, and variable shopId, but print_r($shop); doesn't show anything. How can i see the value of shop variable?
Try this
echo $shop->__toString();
Hi there you might want to try this one:
print_r($this->getAllParams());
instead of using $_POST
$shop = $this->getServiceLocator()
->get('Catalog\Model\Shop')
->findOneBy(array('id' => $shopId, 'user' => $logedUser->getId()));
please remove ->getRepository() from your code, then you will get your result.
At this point we dont know what the Service/Factory 'Catalog\Model\Shop' does. I assume it get's the Entity manager. The query looks ok to me 2. But having 3 return's is just wrong!
Your view will never have the $shop; nor the $view; variable in your .phtml view File. In ZF2 you can just return a Array to your view like so:
return array('shop' => $shop, 'logedUser' => $logedUser);
This will save those variables within your save.phtml
in /yourmodule/view/yourcontroller/save.phtml
If you want to set the .phtml matching yourself you indeed could use the view model like you tried in your code the procedure is a litle diffrent then. It could look like this:
$viewModel = new ViewModel(array(
'logedUser' => $logedUser,
'shop' => $shop,
));
$viewModel->setTemplate('yourmodul/yourcontroller/save');
return $this->getContainerViewModel($viewModel);
Once you have that you can just access your variables in the save.phtml template file like so:
<?php echo $shop->getSomething(); ?>
You did not show us the Shop entity but I assume it has methods like getName(), __toString() etc. You can just call these Object methods within your view.
If you still have trouble understanding the mvc concept of zf2 you might want to re-read the zf2 documentation.
You have to show us what Catalog\Model\Shop and what query are you using for getting your data. Is there possibility that your query just getting null because it fails to get anything from database ? Do you have any kind of checks in your model to find out is your result from query good?
I have a SectorModel with this function:
public function update(Sector $sector) {
$this->db->where('sector_id', $sector->getScetor_id());
return $this->db->update(_SECTOR_, $sector);
}
There are times that I’ll change only the name of the Sector object:
$Sector = new Sector();
$Sector->setSector_name = 'test';
$this->SectorModel->update($Sector);
The generated select looks like:
UPDATE realestate_sector SET sector_name = 'teste', sector_description = NULL
It will update but will set all other properties to NULL because it was not set on my object.
Right now, I have to fill the whole object before sending it.
Is there a way to map the Sector class and update only what was sent on the object?
Thanks in advance for any help.
Sorry for any typos, my English is not good =)
Just loop through all your object's properites and then if any is NULL just drop it with unset.
Here is your model's method edited to achieve that:
public function update(Sector $sector)
{
foreach($sector as $k=>$v)
{
if($v === NULL)
unset($sector->$k)
}
$this->db->where('sector_id', $sector->getScetor_id());
return $this->db->update(_SECTOR_, $sector);
}
Here you can find some info about iterating objects in PHP
The easiest to do this would be to rather use a array - docs here http://codeigniter.com/user_guide/database/active_record.html#update - you just create a array of all the columns with their values that you want to update and perform a $this->db->update('mytable', array('name' => 'test'), array('id' => $id)); call. This will only update the columns you specified in the First array. With the second array acting as your WHERE expression.
The only reason I can think of as to why your other values are being set to NULL is because in your example you create a new instance of the class and the other values must either have been set to nothing or are set to NULL. It would (If this is the case) be better to get a record from the table and then change and values on the populated record and pass that to the function to update.
Hope that helps.