I have a database of questions which are viewed in localhost:8000/questions/{id}. I have created a chatbot in the existing laravel project. Now, I want to provide the user with the link of the question.
For example, if I want the link to a question of id=55, then the bot has to reply me with the link localhost:8000/questions/55.
How do I do that?
web.php
Route::resources([ 'questions' => 'QuestionController', ]);
Route::match(['get', 'post'], '/botman', 'BotManController#handle');
QuestionController.php
public function show(Question $question) {
return view('question')->with('question', $question);
}
botman.php
use BotMan\BotMan\BotMan;
use BotMan\BotMan\BotManFactory;
use BotMan\BotMan\Cache\DoctrineCache;
use BotMan\BotMan\Drivers\DriverManager;
use App\Conversations\StartConversation;
DriverManager::loadDriver(\BotMan\Drivers\Web\WebDriver::class);
$cachedriver = new Doctrine\Common\Cache\PhpFileCache('cache');
BotManFactory::create(config('botman', new
DoctrineCache($cachedriver)));
$botman = app('botman');
$botman->hears('Hello|Hi',
function($bot) {
$bot->typesAndWaits(1);
$bot->startConversation(new StartConversation);
}
);
BotManController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use BotMan\BotMan\BotMan;
use BotMan\BotMan\BotManFactory;
use BotMan\BotMan\Messages\Conversations;
use App\Conversations\StartConversation;
class BotManController extends Controller {
public function handle() {
$botman = app('botman');
$botman->listen();
}
public function startConversation(Botman $bot) {
$bot->startConversation(new StartConversation());
}
}
first we get all the ids from the questions table:
$questions = DB::table('questions')->select('id')->where('body', 'like', '%' . $answer . '%')->get();
$ids here is a collection of id so for each id we must create a link:
$links = array();
foreach($questions as $question){
$links[] = route('questions.show', ['id' => $question->id]);
}
so now we have all links needed to return as answer, finish it using $this->say... as you wish
you may want to return the first link not all links then get the first id from the database and create link using it:
$question = DB::table('questions')->select('id')->where('body', 'like', '%' . $answer . '%')->first()
$link = route('questions.show', ['id' => $question->id]);
then return the answer using $this->say
I hope this helps
Related
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\News;
use App\User;
use App\Event;
public function index()
{
$datanews['newss'] = News::orderBy('created_at','desc')->get();
$dataevent['events'] = Event::orderBy('created_at','desc')->get();
$user['users'] = User::all();
return view('user/aktuelles.index',$datanews, $dataevent,$user);
}
this is a part of my controller, i can show news and events in my view but everytime it says it can not find the variable user?
i dont know why because i dont know why it shows me the other variables but not the user variable???
in my view i can see the other variables like this:
#foreach ($newss as $news)
{{$news->newstitel}}
#endforeach
but i want to show user like this:
{{$user[1]->avatar}}
i tried everything so i tried so look my controller like this:
$user = DB::table('users')->get();
or get the variable via compact
and i tried exactly the same so like this
$user['users'] = User::orderBy('created_at','desc')->get();
and a foreach in my view but it can not found the variable user??
i dont know why
this is the error
Undefined variable: users
return view('user.aktuelles.index', compact('datanews', 'dataevent', 'user');
I am not sure how the helper view() handles the 4th parameter you are passing. According to the docs you can pass data like this:
return view('user/aktuelles.index',[
'datanews' => $datanews,
'dataevent' => $dataevent,
'user' => $user,
]);
or
return view('user/aktuelles.index')->with([
'datanews' => $datanews,
'dataevent' => $dataevent,
'user' => $user,
]);
Maybe give this way a try.
Edit:
The view() helper accepts 3 Parameters: $view = null, $data = [], $mergeData = [] so the 4th parameter you are trying to pass is not even working. You have to pass your data as second parameter or with the chained function with(array $data).
You have to return value in view like below method:
Change this line
$user['users'] = User::orderBy('created_at','desc')->get();
To
$user = User::orderBy('created_at','desc')->get();
return view('user/aktuelles.index', ['datanews' => $datanews,'dataevent'=> $dataevent,'users'=>$user]);
Now, You will get result inside your view using 'users'.
You are not passing variables to view correctly use with or compact to pass variables to view.
i prefer compact as it is simple and easier.
Passing data to view using compact:
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\News;
use App\User;
use App\Event;
public function index()
{
$datanews = News::orderBy('created_at','desc')->get();
$dataevent = Event::orderBy('created_at','desc')->get();
$user = User::all();
return view('user.aktuelles.index',compact('datanews', 'dataevent','user'));
}
Passing variables to view using with:
public function index()
{
$datanews = News::orderBy('created_at','desc')->get();
$dataevent = Event::orderBy('created_at','desc')->get();
$user = User::all();
return view('user.aktuelles.index)->with(['datanews' => $datanews,'dataevent'=> $dataevent,'users'=>$user]);
}
You should try this:
use Illuminate\Support\Facades\DB;
use App\News;
use App\User;
use App\Event;
public function index()
{
$data['news'] = News::orderBy('created_at','desc')->get();
$data['events'] = Event::orderBy('created_at','desc')->get();
$data['users'] = User::all();
return view('user/aktuelles.index', $data);
}
I am filtering results via request()->variable. When there is only one variable the view comes back as it should eg.../products/summer, displaying only products that belong to a certain season.
What i'm trying to do is call in a second variable /products/summer?product_category=shirts displaying the season products as above while filtering those that belong to a specific category (eg.shirts).
This is my controller part:
public function index()
{
if (request()->season) {
$products = Product::with('seasons')->whereHas('seasons', function ($query){
$query->where('slug', request()->season);
})->get();
$product_categories = ProductCategory::with('seasons')->whereHas('seasons', function ($query){
$query->where('slug', request()->season);
})->get();
$season = Season::where('slug', request()->season)->firstOrFail();
} **elseif (request()->product_category)** {
$products = Product::with('product_categories')->whereHas('product_categories', function ($query){
$query->where('slug', request()->product_category);
})->get();
$product_categories = ProductCategory::with('seasons')->get();
$season = Season::where('slug', request()->season)->first();
}......
return view('season')->with([
'products' => $products,
'product_categories' => $product_categories,
'season' => $season,
]);
Is there a way to include season and product_category in the elseif above so that it corresponds to summer?product_category=shirts ?
My nav link passes this:
href="{{ route ('season.index',['season' => $season->slug, 'product_category' => $product_category->slug])}}"
The route is:
Route::get('/products/{season?}', 'SeasonController#index')->name('season.index');
Thank you for your time.
I did not understand exactly what you need
If this code was not useful,plese explan more and i change it:
my view :
<a
href="{{ route ('season.index',['season' =>$season->slug, 'product_category' => $product_category->slug])}}"
>send</a>
my route :
Route::get('/products', 'SeasonController#index')->name('season.index');
SeasonController controler :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SeasonController extends Controller
{
public function index(Request $request)
{
if ($request->get('season'))
{
# do something
}elseif($request->get('product_category'))
{
# do something
}
else
{
# do something
}
}
}
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
I am using laravel 5.1. This is my code,
routes.php
Route::any('users/search', array('as' => 'adminuserssearch', 'uses' => 'UsersController#adminSearch'));
UsersController.php
public function adminSearch(){
$input = Input::all();
if(!empty($input)){
$key = Input::get('key');
$users = User::where('users.name', 'like', '%'.$key.'%')
->orWhere('users.email', 'like', '%'.$key.'%')
->paginate(10);
return view('admin.users.search', ['users' => $users,'tag' =>$key]);
}
}
search.blade.php
{!! $users->render() !!} //Use this code for display pagination.
When I search for a user, the url is like,
http://myproject/admin/users/search?key=user
But when I click pagination link the url will be like,
http://myproject/admin/users/search/?page=2
the ?key=user section will be lost from the url. How can I fix this problem ?
You should append this param to your pagination links .
{!! $users->appends(['key' => $tag])->render() !!}
In Laravel 8 change your UsersController.php by adding ->withQueryString() to ->paginate(10) e.g
public function adminSearch(){
$input = Input::all();
if(!empty($input)){
$key = Input::get('key');
$users = User::where('users.name', 'like', '%'.$key.'%')
->orWhere('users.email', 'like', '%'.$key.'%')
->paginate(10)->withQueryString(); //add withQueryString()
return view('admin.users.search', ['users' => $users]);
}
}
Yourwelcome: Source
You can costumize the paginator URL using the setPath() method.
You can add it to your controller like this $users->setPath('custom/url');
A solution that worked for me:
https://laravel.io/forum/11-15-2016-ho-to-paginate-search-results
The accepted solution says:
in your view where you display pagination...
{{ $results->appends(Request::except('page'))->links() }}
How to use ActiveRecotd cache for Yii 2? I did't find any examples in official docs. In Google I found 2 examples, first is:
$db = self::getDb();
$object = $db->cache(function ($db) use($id) {
return self::findOne($id);
});
But it doesn't work for Model, I tested with updated framework. Other example is:
$data = \Yii::$app->cache->get('some_var_' . $id);
if ($data === false)
{
$data = self::findOne($id);
\Yii::$app->cache->set('some_var_' . $id, $data, 60);
}
It's working fine, but it's not ActiveRecord caching it's data caching, So we haven't got ActiveRecord caching in Yii 2?
1) Use cache like that:
$db = Yii::$app->db;// or Category::getDb()
$result = $db->cache(function ($db) use ($id) {
return Category::find()->where(['id' => $id])->all();
}, CACHE_TIMEOUT);
2) If you may use query dependency, use like that:
$db = Yii::$app->db;// or Category::getDb()
$dep = new DbDependency();
$dep->sql = 'SELECT count(*) FROM category';
$result = $db->cache(function ($db) use ($id) {
return Category::find()->where(['id' => $id])->all();
}, CACHE_TIMEOUT, $dep);
I too am having trouble with this. Here's my workaround for the time being for a hasOne() relationship.
public function getGroup()
{
if(isset(static::$_getGroup[$this->id])) {
return static::$_getGroup[$this->id];
}
$Group = $this->hasOne(BillChargesGroup::className(), ['id' => 'group_id'])->one();
static::$_getGroup[$this->id] = $Group;
return $Group;
}
I only want to cache data for the current request, so this works. However because I'm using ->one(); it does not return the ActiveQuery object if we call $model->getGroup() (which I found is good for extending queries)
Unfortunately if I do return the ActiveQuery object, Yii2 does some "magic" on it and always does a SELECT * which I can't control.
Since 2.0.14 you can use the following shortcuts:
(new Query())->cache(7200)->all();
// and
User::find()->cache(7200)->all();
Source: https://www.yiiframework.com/doc/guide/2.0/en/caching-data