how to Automatically calculate expiry date in backpack laravel? - laravel

i have a field which name is month what i want is when user set the month it automatic calculate with created at month and then upload it to database.
PS - sorry i am new at laravel
Please see Edit:
my store method looks like
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
// VALIDATION: change the requests to match your own file names if you need
form validation
use App\Http\Requests\ClientsRequest as StoreRequest;
use App\Http\Requests\ClientsRequest as UpdateRequest;
use Carbon\Carbon;
class ClientsCrudController extends CrudController
{
public function setup()
{
$this->crud->setModel('App\Models\Clients');
$this->crud->setRoute(config('backpack.base.route_prefix') . '/clients');
$this->crud->setEntityNameStrings('clients', 'clients');
$this->crud->setFromDb();
}
public function store(StoreRequest $request)
{
// your additional operations before save here
$start_day = Carbon::parse($request->created_at);
$expiry_day = $start_day->addMonths($request->month);
$request->input($expiry_day);
$redirect_location = parent::storeCrud($request);
// your additional operations after save here
// use $this->data['entry'] or $this->crud->entry
return $redirect_location;
}
public function update(UpdateRequest $request)
{
// your additional operations before save here
$redirect_location = parent::updateCrud($request);
// your additional operations after save here
// use $this->data['entry'] or $this->crud->entry
return $redirect_location;
}
}

Assuming that you mean months ammount ( i.e for a monthly payment )
You can do it like this in your store method i.e:
$start_day = Carbon::parse($request->created_at); //get a carbon instance with created_at as date
$expiry_day = $start_day->addMonths($request->user_selected_months); //add X months to created_at date

public function store(StoreRequest $request) {
date_default_timezone_set('asia/calcutta');
$month = $request->month;
$expiry_date = Carbon::now()->addMonths($month);
$request['expiry_date'] = $expiry_date;
}

Related

how to hide id from url in Laravel 6?

hide id from url
https://wallpaperaccess.in/photo/162/download-wallpaper
i want url like this
https://wallpaperaccess.in/photo/download-wallpaper
ImagesController.php
public function show($id, $slug = null ) {
$response = Images::findOrFail($id);
$uri = $this->request->path();
if( str_slug( $response->title ) == '' ) {
$slugUrl = '';
} else {
$slugUrl = '/'.str_slug( $response->title );
}
$url_image = 'photo/'.$response->id.$slugUrl;
//<<<-- * Redirect the user real page * -->>>
$uriImage = $this->request->path();
$uriCanonical = $url_image;
if( $uriImage != $uriCanonical ) {
return redirect($uriCanonical);
}
Route
// Photo Details
Route::get('photo/{id}/{slug?}','ImagesController#show');
NOTE: i don't have any slug column in database, so can we use title as slug?
You should add a column field slug and auto-generate it from title
use Illuminate\Support\Str;
$slug = Str::slug($request->input('title'), '-');
In Models\Image.php
public function getRouteKeyName()
{
return 'slug';
}
In routes\web.php
Route::get('photo/{image:slug}','ImagesController#show');
In app\Http\Controllers\ImagesController.php
use app\Models\Image.php;
...
public function show(Image $image)
{
// controller will automatically find $image with slug in url
// $image_id = $image->id;
return view('your.view', ['image' => $image]);
}
In order to use a slug in the URL instead of an id, you'll need to...
Create a column in your table where you store the slug. A good way to make a slug unique is to append the actual id at the end. If you really don't want to see the id anywhere, you have no choice, you'll have to ensure the slug is unique yourself (there are a lot of ways to achieve this).
This is one way to automatically create an unique slug:
Make sure the slug column is nullable, then open your model and add these methods.
They are called "model events".
created is called when the model is, well, created.
updating is called when you are updating the model but before it's actually updated.
Using created and updating should automatically create the slug when you create or update a Images instance.
protected static function booted()
{
parent::booted();
static::created(function (Images $images) {
$images->slug = Str::slug($images->title.'-'.$images->id);
$images->save();
});
static::updating(function (Images $images) {
$images->slug = Str::slug($images->title.'-'.$images->id);
});
}
From a SEO point of view, updating the slug when the title change is arguably not a good practice, so you might want to omit this part (static::updating...), it's up to you.
Go to your model and add the following method:
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug'; //or whatever you call the slug column
}
This way, the router will resolve your model by the slug, not the id.
In your route file, remove the id and change the name of the slug to match the name of your model:
Route::get('photo/{images}','ImagesController#show'); //here I'm assuming your model is Images from what I see in your controller
In your controller, change the declaration of your show method to this:
public function show(Images $images)
{
dd($images);
// if you did all this correctly, $images should be the Images corresponding to the slug in the url.
// if you did something wrong, $images will be an empty Images instance
//
//
// your code...
}
Images should be renamed to Image, models should not be plural. However, it should not make any difference here.

Laravel set a common validator for all date fields in the system

I have different date fields in different models, I need to validate these date fields format on save of each model accordingly. is this possible?
Of course, you can. You just need to add this code below to your Model.
public static $rules = [
'date'=> 'reqired|date_format:MM:dd:YYYY' //if date is not required, ommite it
]
You can use different formats for your date in your different Models like MM:dd etc. Hope this helps you.
EDIT
To be able to use multiple date formats in a single validator You can define the multi-format date validation in your AppServiceProvider with the following code:
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Validator::extend('date_multi_format', function($attribute, $value, $formats) {
// iterate through all formats
foreach($formats as $format) {
// parse date with current format
$parsed = date_parse_from_format($format, $value);
// if value matches given format return true=validation succeeded
if ($parsed['error_count'] === 0 && $parsed['warning_count'] === 0) {
return true;
}
}
// value did not match any of the provided formats, so return false=validation failed
return false;
});
}
}
You can later use this new validation rule like that:
'date' => 'date_multi_format:"Y-m-d H:i:s.u","Y-m-d"' //or any other format
Hope this helps, thanks.

Unable to respond to more than one click on an interactive message

I want to be able to retrieve responses from:
a) as many people on the channel
b) identify the user who chose what option
For some reason, after the first person has clicked, thereafter any response just goes to the fallback.
How would I achieve this? and this is my file
This is my controller page:-
namespace App\Conversations;
namespace App\Http\Controllers;
use App\Conversations\ExampleConversation;
use App\Conversations\MenuConversation;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\Drivers\Slack\Extensions\Menu;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
class BotSlackController extends Controller
{
public function getSlackUsers()
{
$guzzle = \App::make(Client::class);
$user_data = [];
$slack_token = "xoxb-2893074844-363165652051-cCiOK0lMGHf5e72QF6s04Nbl";
$user_list_url = "https://slack.com/api/users.list?token=$slack_token&pretty=1";
$user_list = $guzzle->request('GET', $user_list_url)->getBody()->getContents();
$user_list = json_decode($user_list);
if (!empty($user_list->members)) {
foreach ($user_list->members as $user_info) {
if ($user_info->deleted == true) {
continue;
}
$user_data[] = ['id' => $user_info->id, 'name' => $user_info->real_name];
}
}
return $user_data;
}
public function sendMessageView()
{
$slack_users = $this->getSlackUsers();
return view('slackMessage', ['slack_users' => $slack_users]);
}
public function sendControllerBot(Request $request) {
/*$data = \App::make(ExampleConversation::class);
$data->sendBot($request);*/
$botman = app('botman');
$user_id = $request['slackUserId'];
$user_msg = $request['slackMessage'];
$botman->startConversation(new MenuConversation(),$user_id,\BotMan\Drivers\Slack\SlackDriver::class);
//$botman->listen();
}
}
This is my MenuConversation file:-
<?php
namespace App\Conversations;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Conversations\Conversation;
class MenuConversation extends Conversation
{
public function askBtn()
{
$question = Question::create("Hello, How are you?")
->fallback('Unable to create a new database')
->callbackId('ask_btn')
->addButtons([
Button::create('I am fine')->value('fine'),
Button::create('Not good')->value('no_good'),
Button::create('Do not disturb')->value('wont_disturb')
]);
return $this->ask($question, function (Answer $answer) {
if ($answer->isInteractiveMessageReply()) {
$result = $answer->getValue();
//Will actually store it in a DB and yet to figure how to retrieve the Slack User that selected the option
/\* $this->say("Hello I got your response. Response: ".$result); \*/
$this->bot->reply("Hello I got your response. Response: ".$result);
}
});
}
public function run()
{
$this->askBtn();
}
}
First time when I click any button I get the value of the button I clicked but immediate after second click it goes to my fallback function which I created in botman.php.
Please anyone help me out in this.
How I can get multi-response(or multi time click response)
If I send a message in public channel instead of Particular user, How I can fetch the user Id who clicked the button.

Laravel API APP Many-Many Relationship, how to return specific information in JSON?

I been trying to figure this out for some time now. Basically i got 2 models ' Recipe ', ' Ingredient ' and one Controller ' RecipeController ' .
I'm using Postman to test my API. When i go to my get route which uses RecipeController#getRecipe, the return value is as per the pic below:
Return for Get Route
If i want the return value of the get route to be in the FORMAT of the below pic, how do i achieve this? By this i mean i don't want to see for the recipes: the created_at column, updated_at column and for ingredients: the pivot information column, only want name and amount column information.
Return Value Format I Want
Recipe model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Recipe extends Model
{
protected $fillable = ['name', 'description'];
public function ingredients()
{
return $this->belongsToMany(Ingredient::class,
'ingredient_recipes')->select(array('name', 'amount'));
}
}
Ingredient Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ingredient extends Model
{
protected $fillable = ['name', 'amount'];
}
RecipeController
<?php
namespace App\Http\Controllers;
use App\Ingredient;
use App\Recipe;
use Illuminate\Http\Request;
class RecipeController extends Controller {
public function postRecipe(Request $request)
{
$recipe = new Recipe();
$recipe->name = $request->input('name');
$recipe->description = $request->input('description');
$recipe->save();
$array_ingredients = $request->input('ingredients');
foreach ($array_ingredients as $array_ingredient) {
$ingredient = new Ingredient();
$ingredient->name = $array_ingredient['ingredient_name'];
$ingredient->amount = $array_ingredient['ingredient_amount'];
$ingredient->save();
$recipe->ingredients()->attach($ingredient->id);
}
return response()->json(['recipe' => $recipe . $ingredient], 201);
}
public function getRecipe()
{
$recipes = Recipe::all();
foreach ($recipes as $recipe) {
$recipe = $recipe->ingredients;
}
$response = [
'recipes' => $recipes
];
return response()->json($response, 200);
}
API Routes:
Route::post('/recipe', 'RecipeController#postRecipe')->name('get_recipe');
Route::get('/recipe', 'RecipeController#getRecipe')->name('post_recipe');
Thanks Guys!
I think your best solution is using Transformer. Using your current implementation what I would recommend is fetching only the needed field in your loop, i.e:
foreach ($recipes as $recipe) {
$recipe = $recipe->ingredients->only(['ingredient_name', 'ingredient_amount']);
}
While the above might work, yet there is an issue with your current implementation because there will be tons of iteration/loop polling the database, I would recommend eager loading the relation instead.
But for the sake of this question, you only need Transformer.
Install transformer using composer composer require league/fractal Then you can create a directory called Transformers under the app directory.
Then create a class called RecipesTransformer, and initialize with:
namespace App\Transformers;
use App\Recipe;
use League\Fractal\TransformerAbstract;
class RecipesTransformer extends TransformerAbstract
{
public function transform(Recipe $recipe)
{
return [
'name' => $recipe->name,
'description' => $recipe->description,
'ingredients' =>
$recipe->ingredients->get(['ingredient_name', 'ingredient_amount'])->toArray()
];
}
}
Then you can use this transformer in your controller method like this:
use App\Transformers\RecipesTransformer;
......
public function getRecipe()
{
return $this->collection(Recipe::all(), new RecipesTransformer);
//or if you need to get one
return $this->item(Recipe::first(), new RecipesTransformer);
}
You can refer to a good tutorial like this for more inspiration, or simply go to Fractal's page for details.
Update
In order to get Fractal collection working since the example I gave would work if you have Dingo API in your project, you can manually create it this way:
public function getRecipe()
{
$fractal = app()->make('League\Fractal\Manager');
$resource = new \League\Fractal\Resource\Collection(Recipe::all(), new RecipesTransformer);
return response()->json(
$fractal->createData($resource)->toArray());
}
In case you want to make an Item instead of collection, then you can have new \League\Fractal\Resource\Item instead. I would recommend you either have Dingo API installed or you can follow this simple tutorial in order to have in more handled neatly without unnecessary repeatition

Laravel profile edit

Alright , I have used this way to save the users info and It works perfect,
static public function memberSave($request) {
$signup = false;
$member = new Members();
$member->name = $request['name'];
$member->email = $request['email'];
$member->password = bcrypt($request['password']);
$member->save();
if (!empty($member->id)) {
$new_id = $member->id;
DB::insert("INSERT INTO roles VALUES ($new_id, 5613)");
$signup = true;
Session::flash('sm', 'Thank you! You have signed up successfully!');
}
return $signup;
}
but when making this for editing the profile(by user) It doesn't work
becuase I use new(); (making object)
I also didn't succeed to use find(); so I tried to use this
static public function saveProfile($id,$name,$email,$password) {
$sql = "UPDATE members SET name=?,email=?,password=? WHERE id=?";
$member = DB::select($sql, [$name,$email,$password,$id]);
but when I want to bcrypt the password in laravel doesnt work .
this is the code also in the second page
public function postProfile(ProfileValidation $request) {
if (Members::saveProfile($request['id'], $request['name'], $request['email'], $request['password'])) {
return redirect('');
}
}
I hope getting helped for editing the users profile by laravel , thanks.
Your Members class must extend Eloquent\Model for following this code to work.
class Members extends Model {
// optional
protected $table = 'members';
...
To find and update the member using email,
// find the single member
$member = Members::where('email', request['email'])->first();
// update the member
$member->name = $request['name'];
$member->password = $request['password'];
// now save the updated member
$member->save();
In order to to encrypt Password, Laravel provides Hash Facade,
// import this
use Hash;
...
// encrypt Password
$encrypted = Hash::make($request['password']);
...
if you want your user automatically hash the password at your model put:
public function setPasswordAttribute($value)
{
$this->attributes['password'] = Hash::make($value);
}
and you can directly check for the user if exist create new or update it:
public function saveMember($request)
{
$member = Member::findOrNew($request->email);
//All your input you want to save
$member->save();
}

Resources