How can i get the buyers to still be able to purchase the product even if its unavailable? - laravel

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

Backpack V4 modifying field before store

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.

Accessing parameters in Request

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.

Error using save( ) in Laravel command

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();

Routing with parameters - Laravel

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.

getting the value of the single field output using the codeigniter active record

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;
}

Resources