I'm trying to create waitlist to buy product, but change the status of the transaction from 'Confirmed' to 'Waitlist'.
For that I have added a variable 'status' and a function in Transaction Model as follows:
const CONFIRMED_TRANSACTION = 'confirmed';
const WAITLIST_TRANSACTION = 'waitlist'; //waitlist product
public function isConfirmed() {
return $this->status == Transaction::CONFIRMED_TRANSACTION;
}
Default value of Transaction->status is 'CONFIRMED_TRANSACTION'.
Now every time the Product->status changes to 'unavailable' i would like to change the value of the Transaction->status to 'WAITLIST_TRANSACTION' when the transaction is created.
I am trying to achieve it using Event Listeners as:
Transaction::created(function($transaction) {
if(!$product->isAvailable()) {
$transaction->status = Transaction::WAITLIST_TRANSACTION;
$transaction->save();
}
});
But this gives me error :
**ErrorException: Undefined variable: product in file /home/vagrant/restfulapi7/app/Providers/AppServiceProvider.php on line 29**
How can I achieve the same in a better way?
You're using what's called a lambda or anonymous function, which has a different scope to the rest of your code.
function($transaction) does not have access to a variable named $product. So you're trying to call ->isAvailable() on a variable which doesn't exist.
Transaction::created(function($transaction) {
if(!$product->isAvailable()) {
$transaction->status = Transaction::WAITLIST_TRANSACTION;
$transaction->save();
}
});
Assuming it exists in the scope in which you call Transaction::created(), you can pass the $product variable into your lambda function like this:
function($transaction) use ($product) { ... }
For more information on lambda functions, read the php docs here
This solves the issue:
if(!$transaction->product->isAvailable())
Related
In 3.6 version of backpack I can change an attribute value before storing it.
I have this code
If ($request->description == "") {
$request->description="User has not entered any description";
}
$redirect_location = parent::storeCrud($request);
What can I do to get the same in V4? I'm reading this guide but I can't make it to work.
This is what I'm trying in V4
public function store(PedidoRequest $request)
{
Log::debug('testing...');
If ($request->description == "") {
$request->description="User has not entered any description";
}
$redirect_location = $this->traitStore();
return $redirect_location;
}
The Request object in Laravel, Illuminate\Http\Request, doesn't have the ability to set the inputs via the properties like that, no __set method ($request->description = '...' does not set an input named description). You would have to merge the inputs into the request or use the array syntax to do that:
$request->merge(['description' => '...']);
// or
$request['description'] = '...';
But since backpack seems to have abstracted things apparently you aren't controlling anything in your controller methods you could try this:
$this->crud->request->request->add(['description'=> '...']);
Potentially:
$this->request->merge(['description' => '...']);
That would be assuming some trait the Controller uses is using the Fields trait.
I have a question about obtaining parameters from Request object.
What is the difference between
$name = $request->name;
OR
$name = $request->input("name");
They show the same behavior. I am asking that from the typing perspective, it is faster to utilize #1 method. But I don't know the difference. Is #1 prone to SQL injections?
Basically, the first case is just a syntactic sugar for the second. In Laravel, Request implements __get magic function to access its internal properties.
public function all()
{
return array_replace_recursive($this->input(), $this->allFiles());
}
public function __get($key)
{
$all = $this->all();
if (array_key_exists($key, $all)) {
return $all[$key];
} else {
return $this->route($key);
}
}
In the first case, if any files were uploaded, Laravel first looks for a property amongst them. And if there is no such param in files or in input, in your first snippet, Laravel also looks for a value amongst route parameters:
To protect your code against SQL injections, you have to use prepared statements/query builder/ORM. You should not escape/change input, so both these functions don't protect you against SQL injections.
I am setting up my first Laravel command, but having an issue saving the the record.
My model:
Public static function contractorDecline(){
return DB::table('job_interviews')
->where('job_interviews.status', '=', 'awaiting contractor response')
->get();
}
I set up a command to change the status after 24 hours with no action:
public function fire()
{
//
$tooLate = Carbon::Now()->subHours(24);
$interviews = JobInterview::contractorDecline();
//
foreach($interviews as $interview){
if ($interview->response_received_on <= $tooLate){
$interview->status = 'contractor declined interview';
$interview->save();
}
}
return('finished');
}
When I run the command, I am getting the error:
"Call to undefined method stdClass::save()"
What do I need to add to the controller to be able to use save() in the command?
You are using Fluent which returns a simple object and calling Eloquent save method on it. If you want to update the row you should use Eloquent instead. Assuming you have a JobInterview class(Model) for the job_interviews table, you can code:
JobInterview::whereStatus('awaiting contractor response')->get();
I'm trying to craft a route for a controller that will submit some data to a database. My URL is as follows:
http://example.co.uk/posts/5/edit?type=job
I've tried
Route::post('/posts/{id}/edit?type={role}', 'PostsContoller#store');
but am unsure if this will fly?
Don't add parameters in your route:
Route::post('/posts/{id}/edit', 'PostsContoller#store');
In your controller, just check if parameter exist:
$type = Input::has('type') ? Input::get('type') : null;
Don't worry about HTTP verb, as Input access for all verbs (POST,GET,PUT,DELETE...).
Edit
As pointed out by #Antoine, you can simply specify the default value in the get method
$type = Input::get('type', null);
I don't think that this is the right way to do it.
First way
If you change your route to
Route::post('/posts/{id}/edit/{role?}', 'PostsContoller#store');
You will then call the URL: GET posts/42/edit/job.
your store function in PostsController will be:
public function store($id, $role = null)
{
// some code
}
Second way
You can use another route like:
Route::post('/posts/{id}/edit', 'PostsContoller#store');
You will then call the URL: GET posts/42/edit?type=job
And you can get the type in your store function in PostsController:
public function store($id)
{
// $role will be null if type is not in the URL
$role = Input::get('type', null);
// additional code
}
I would personally go for the second way.
the following function is supposed to read the name of the given asset code from the database. but it triggers the error: "Trying to get property of non-object"
function sban_name($asset){
$this->db->select('name');
$this->db->from('asset_types');
$this->db->where('code',$asset);
return $this->db->get()->result()->row('name');
}
All I want is to have the name of the asset returned back to the controller! Your help is highly appreciated!
Use row() like,
return $this->db->get()->row()->name;
Use row() for a single row, and result() for multiple rows.
do like this, asset_types is your table name
function sban_name($asset){
$this->db->select('name');
$this->db->from('asset_types');
$this->db->where('code',$asset);
return $this->db->get('asset_types');
}
And in your controller acess it like
$result=$this->modelname->sban_name('$asset')->row();
$name=$result->name;
I think it's important to check if the record that satisfies the conditions even exists in the database. Code for the model:
function sban_name($asset){
$this->db->select('name');
$this->db->from('asset_types');
$this->db->where('code',$asset);
$row = $this->db->get()->row();
if (isset($row)) {
return $row->name;
} else {
return false;
}
}
Simply call the function from the controller like so:
$response = $this->model_name->sban_name($asset)
Try this code of block , I already checked and works fine:
function sban_name($asset)
{
$this->db->select('name');
$this->db->from('asset_types');
$this->db->where('code', $asset);
return $this->db->get()->row()->name;
}