I am trying to use ajax smart search,
http://maxoffsky.com/code-blog/laravel-shop-tutorial-3-implementing-smart-search/
But my application can not find the controller I used from the tutorial above.
This is the error i get:
Class App\Http\Controllers\Api\ApiSearchController does not exist
After googling this error message I found out that it is caused by an incorrect route. But I believe I set my routes correctly.
This is my route:
Route::get('api/search', 'Api\ApiSearchController#index');
And here is my controller:
<?php namespace App\Http\Controllers;
use App\Http\Controllers\Base\Controller;
class ApiSearchController extends Controller {
public function appendValue($data, $type, $element)
{
// operate on the item passed by reference, adding the element and type
foreach ($data as $key => & $item) {
$item[$element] = $type;
}
return $data;
}
public function appendURL($data, $prefix)
{
// operate on the item passed by reference, adding the url based on slug
foreach ($data as $key => & $item) {
$item['url'] = url($prefix.'/'.$item['slug']);
}
return $data;
}
public function index()
{
$query = e(Input::get('q',''));
if(!$query && $query == '') return Response::json(array(), 400);
$products = Product::where('published', true)
->where('name','like','%'.$query.'%')
->orderBy('name','asc')
->take(5)
->get(array('slug','name','icon'))->toArray();
$categories = Category::where('name','like','%'.$query.'%')
->has('products')
->take(5)
->get(array('slug', 'name'))
->toArray();
// Data normalization
$categories = $this->appendValue($categories, url('img/icons/category-icon.png'),'icon');
$products = $this->appendURL($products, 'products');
$categories = $this->appendURL($categories, 'categories');
// Add type of data to each item of each set of results
$products = $this->appendValue($products, 'product', 'class');
$categories = $this->appendValue($categories, 'category', 'class');
// Merge all data into one array
$data = array_merge($products, $categories);
return Response::json(array(
'data'=>$data
));
}
}
I think the namespace you specified isn't the one expected :
Class App\Http\Controllers\Api\ApiSearchController does not exist
doesn't match :
<?php namespace App\Http\Controllers;
Related
i have one project in CI3 and update for CI4
i have problem in my template, i receive Call to a member function get() on null.
my view not working call $this->traducao->get('search_string'); please help-me for update in class and libraries
My Function in Libraries
<?php
namespace App\Libraries;
use Config\Database;
class menus {
public $listMenus;
public $listSeo;
public function __construct(){
$this->set();
}
public function set(){
$db = Database::connect();
$builder = $db->table('menu');
$query = $builder->where("parente", 0)
->where("ativo", 1)
->orderBy('posicao', 'asc')
->get()->getResultArray();
if(is_array($query)){
$menusPai = $query;
}
$query2 = $builder->where("parente > 0")
->where("ativo", 1)
->orderBy('posicao', 'asc')
->get()->getResultArray();
if(is_array($query)){
$menusFilhos = $query2;
}
// $menusFilhos = ($query2->countAllResults() > 0) ? $query2->getResultArray() : false;
$menus = [];
foreach ($menusPai as $key => $value)
{
$this->listSeo[$value['link']]['pagina_titulo'] = $value['pagina_titulo'];
$this->listSeo[$value['link']]['pagina_keywords'] = $value['pagina_keywords'];
$this->listSeo[$value['link']]['pagina_description'] = $value['pagina_description'];
$menus[$value['id']]['filhos'] = [];
$menus[$value['id']]['dados'] = $value;
if ($menusFilhos)
{
foreach ($menusFilhos as $k => $v)
{
if ($v['parente'] == $value['id'])
{
$this->listSeo[$v['link']]['pagina_titulo'] = $v['pagina_titulo'];
$this->listSeo[$v['link']]['pagina_keywords'] = $v['pagina_keywords'];
$this->listSeo[$v['link']]['pagina_description'] = $v['pagina_description'];
$menus[$value['id']]['filhos'][] = $v;
}
}
}
}
$this->listMenus = $menus;
}
public function get(){
return $this->listMenus;
}
public function seo($tag){
$uri = new \CodeIgniter\HTTP\URI();
print_r($uri);
$uri = ($this->CI->uri->uri_string() == '') ? '/' : $this->CI->uri->uri_string();
return $this->listSeo[$uri][$tag];
// return $this->listSeo[$uri][$tag];
}
}
My ControllerBase
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Libraries\My_parser;
use App\Libraries\Preferencia;
use App\Models\index_model;
use App\Libraries\Traducao;
use App\Libraries\Menus;
class BaseController extends Controller
{
protected $helpers = [];
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->_db = \Config\Database::connect();
$this->My_parser = new My_Parser();
$this->_model = new \App\Models\index_model();
$this->traducao = new Traducao();
}
public function output($data, $status){
$this->output
->set_status_header(200)
->set_content_type('application/json', 'utf-8')
->set_output(
json_encode(
array(
'status'=> $status,
'response'=> $data
),
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
)
)->_display();
exit;
}
}
And my view
<div class="container">
<h2 class="text-center no-m"><?= $this->traducao->get('HOME_EMPRESAS_PARCEIRAS_TITULO') ?></h2>
and my index.php loading views layout
<?= $this->extend('template/head.php',array('css'=> $css, 'metatags'=> $metatags)) ?>
<?= $this->extend('template/header.php') ?>
<?= $this->extend('template/navbar.php') ?>
<?= $this->section('content')?>
<?= $this->endSection()?>
The short answer is it doesn't exist in the View because you never gave it to the View.
$this->traducao belongs to the Controller. It may have been constructed with the Controller but there's no immediate reason that any View would have access to it (or any data that wasn't passed directly to the View).
All incoming requests should be routed through Controllers; that is their most important purpose. Where is the Controller that's actually handling the request to your index.php file?
Any and all Views should be displayed by a Controller because that is where you have the ability to pass data (i.e. $this->traducao) into the View.
If this is actually CI4 as tagged, then you have a problem with CI3 code still being present as well; for example, $this->output isn't used to return Controller responses in CI4, it's $this->response instead.
I have made dynamic category routes by adding custom class to my app (how i did it is here) now i need to make my blade works with this dynamic path.
Logic
based on categories deeps my url will create such as:
site.com/category/parent
site.com/category/parent/child
site.com/category/parent/child/child
etc.
so far my view is just loading for site.com/category/parent for other urls it return 404 error.
code
CategoryRouteService
class CategoryRouteService
{
private $routes = [];
public function __construct()
{
$this->determineCategoriesRoutes();
}
public function getRoute(Category $category)
{
return $this->routes[$category->id];
}
private function determineCategoriesRoutes()
{
$categories = Category::all()->keyBy('id');
foreach ($categories as $id => $category) {
$slugs = $this->determineCategorySlugs($category, $categories);
if (count($slugs) === 1) {
$this->routes[$id] = url('category/' . $slugs[0]);
}
else {
$this->routes[$id] = url('category/' . implode('/', $slugs));
}
}
}
private function determineCategorySlugs(Category $category, Collection $categories, array $slugs = [])
{
array_unshift($slugs, $category->slug);
if (!is_null($category->parent_id)) {
$slugs = $this->determineCategorySlugs($categories[$category->parent_id], $categories, $slugs);
}
return $slugs;
}
}
CategoryServiceProvider
class CategoryServiceProvider
{
public function register()
{
$this->app->singleton(CategoryRouteService::class, function ($app) {
// At this point the categories routes will be determined.
// It happens only one time even if you call the service multiple times through the container.
return new CategoryRouteService();
});
}
}
model
//get dynamic slug routes
public function getRouteAttribute()
{
$categoryRouteService = app(CategoryRouteService::class);
return $categoryRouteService->getRoute($this);
}
blade
//{{$categoryt->route}} returning routes
<a class="post-cat" href="{{$category->route}}">{{$category->title}}</a>
route
//show parent categories with posts
Route::get('/category/{slug}', 'Front\CategoryController#parent')->name('categoryparent');
controller
public function parent($slug){
$category = Category::where('slug', $slug)->with('children')->first();
$category->addView();
$posts = $category->posts()->where('publish', '=', 1)->paginate(8);
return view('front.categories.single', compact('category','posts'));
}
Note: I'm not sure about this but i think i my route is kinda static! I mean it just getting 1 slug with it while my category can goes 2, 3 or 4 slug deep and it doesn't make sense to me to make several route and keep repeating Route::get('/category/{slug}/{slug}/{slug} like that.
As I said I'm not sure about this, please share your idea and solutions if you may.
UPDATE
based on Leena Patel answer I changed my route but when I get more than 1 slug in my url it returns error:
Example
route: site.com/category/resources (works)
route: site.com/category/resources/books/ (ERROR)
route: site.com/category/resources/books/mahayana/sutra (ERROR)
error
Call to a member function addView() on null
on
$category->addView();
when I comment that it returns error for $posts part. then error for my blade where i returned category title {{$category->title}}
So basically it seem doesn't recognize this function for returning view of category routes.
here is my function
public function parent($slug){
$category = Category::where('slug', $slug)->with('children')->first();
$category->addView();
$posts = $category->posts()->where('publish', '=', 1)->paginate(8);
return view('front.categories.single', compact('category','posts'));
}
any idea?
You can try using Route Pattern like below
Route::get('/category/{slug}', 'Front\CategoryController#parent')->where('slug','.+')->name('categoryparent')
So if you have more than one slugs in your url like /category/slug1/slug2
Your addView() method will work for one record and not for Collection So add foreach loop to achieve this.
public function parent($slug){
// $slug will be `slug1/slug2`
$searchString = '/';
$posts = array();
if( strpos($slug, $searchString) !== false ) {
$slug_array = explode('/',$slug);
}
if(isset($slug_array))
{
foreach($slug_array as $slug)
{
$category = Category::where('slug', $slug)->with('children')->first();
$category->addView();
$posts_array = $category->posts()->where('publish', '=', 1)->paginate(8);
array_push($posts,$posts_array);
}
}
else
{
$category = Category::where('slug', $slug)->with('children')->first();
$category->addView();
$posts = $category->posts()->where('publish', '=', 1)->paginate(8);
}
return view('front.categories.single', compact('category','posts'));
}
Hope it helps!
Documentation : https://laravel.com/docs/4.2/routing#route-parameters
Create route
Route::get('category/{cat}', 'YourController#mymethod');
Add this to your Providers/RouteServiceProvider.php 's boot method
public function boot()
{
Route::pattern('cat', '.+'); //add this
parent::boot();
}
In your method:
public function mymethod($cat){
echo $cat; //access your route
}
You can use optional URL sections in the route and use conditionals in controllers. Try this:
In your route:
Route::get('/category/{parent?}/{child1?}/{child2?}', 'Front\CategoryController#parent')->name('categoryparent');
In your controller:
public function mymethod($category, $parent, $child1, $child2){
if(isset($child2)){
//use $category, $parent, $child1, $child2 and return view
} else if(isset($child1)){
//use $category, $parent, $child1 and return view
} else if(isset($parent)){
//use $category, $parent and return view
} else {
//return view for $category
}
}
this is the result of a Foreach loop get method using dd$($value),
Questions: how do i convert this inside my controller into an array and store it into my database
Example: [Lead_id1=Subjectid1 , Lead_id2=Subjectid1, Lead_id3=Subjectid1]
so on and so fort..
Note: Lead_id and Subject_id are both FK there for the value must be integer Not String
Controller:
public function store(Request $request)
{
$value=$request->all();
$subjects = $value['Subject_id'] ?? [];
$leads = $value['Lead_id'] ?? [];
$data = [];
foreach ($subjects as $subject) {
$data[] = array_combine($leads, array_fill(0, count($leads), $subject));
$scores=new Score;
$scores->Subject_id=$request->input('Subject_id');
$scores->Lead_id=$request->input('Lead_id');
dd($scores);
$scores->save();
}
this is the result
Score Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Score extends Model
{
protected $guarded = [
'id',
'Year_id',
'Term_id',
'Level_id',
'Classes_id',
'Subject_id',
'Lead_id',
];
}
You said Lead_id and Subject_id both are foreign key then you can simply use ManyToMany relation in laravel and save the data accordingly
Subject Model
class Subject extends Model{
public function leads(){
return $this->belongsToMany(Lead::class, 'scores', 'Subject_id', 'Lead_id');
}
}
Lead Model
class Lead extends Model{
public function subjects(){
return $this->belongsToMany(Subject::class, 'scores', 'Lead_id', 'Subject_id');
}
}
Questions: how do i convert this inside my controller into an array and store it into my database
foreach($data['Subject_id'] as $subjectId){
$subject = Subject::find($subjectId);
$leadids = $data['Lead_id'];
$subject->leads()->attach($leadids);
}
For details check this https://laravel.com/docs/5.6/eloquent-relationships#many-to-many
You can try -
$temp = [];
$subject = !empty($value['Subject_id'][0]) ? $value['Subject_id'][0] : null; // extract the subject id
// Loop through lead ids
foreach($value['Lead_id'] as $lead) {
$temp[$lead] = $subject; // store subject id fro lead ids
}
You may try following :
public function store(Request $request)
{
$value=$request->all();
$subjects = $value['Subject_id'] ?? [];
$leads = $value['Lead_id'] ?? [];
$data = [];
foreach ($subjects as $subject) {
$data[] = array_combine($leads, array_fill(0, count($leads), $subject));
}
foreach ($data as $load => $subject) {
$scores = new Score;
$scores->Subject_id = $subject;
$scores->Lead_id = $load;
$scores->save();
dd($scores);
}
}
convert the array first into a json string
json_encode($array);
before store it to the database
I have complex query and relation which I'm not fully understand. I'm kind of new in Laravel. Anyway, I'm looking for a way to load this with slugs instead of ID's.
This is the function in the controller
public function index( $category_id)
{
$Category = new Category;
$allCategories = $Category->getCategories();
$category = Category::find($category_id);
if($category->parent_id == 0) {
$ids = Category::select('id')->where('parent_id', $category_id)->where('parent_id','!=',0)->get();
$array = array();
foreach ($ids as $id) {
$array[] = (int) $id->id;
}
$items = Item::whereIn('category_id',$array)->where('published', 1)->paginate(5);
} else {
$items = Item::where('category_id' ,$category_id)->where('published', 1)->paginate(5);
}
return view('list', compact('allCategories','items'));
}
Those are relations in the Model
public function item()
{
return $this->hasMany('App\Item','category_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id');
}
public function getCategories()
{
$categoires = Category::where('parent_id',0)->get();
$categoires = $this->addRelation($categoires);
return $categoires;
}
public function selectChild( $id )
{
$categoires = Category::where('parent_id',$id)->where('published', 1)->paginate(40);
$categoires = $this->addRelation($categoires);
return $categoires;
}
public function addRelation( $categoires )
{
$categoires->map(function( $item, $key)
{
$sub = $this->selectChild($item->id);
$item->itemCount = $this->getItemCount($item->id , $item->parent_id );
return $item = array_add($item, 'subCategory', $sub);
});
return $categoires;
}
public function getItemCount( $category_id )
{
return Item::where('category_id', $category_id)->count();
}
This is what I have in my routes
Route::get('list/{category}', 'ListController#index')->name('list');
currently is loading urls like http://example.com/list/1 where 1 is the ID. I'm wonder if with current setup is possible to make it like, http://example.com/slug
I'm aware how slugs are working. I just can't understand how to use them in queries instead of ID's
You can use explicit Route Model Binding to grab your Category by slug before processing it.
In your RouteServiceProvider you need to bind the model:
Route::bind('category', function ($value) {
//Change slug to your column name
return App\Category::where('slug', $value)->firstOrFail();
});
Then, you can typehint the categories.
For example in your index method:
public function index(Category $category)
{
$Category = new Category;
$allCategories = $Category->getCategories();
//This line is obsolete now:
//$category = Category::find($category_id);
//...
}
Try to change your index function parameter from $category_id to $category_slug
Remove this line $Category = new Category;
And change this $category = Category::find($category_id);
To this: $category = Category::where('slug', $category_slug)->first();
*Assuming that you have a unique slug in category table
I am using laravel 5.4 and I want to filter search. its my front-end
my code looks like this
class DeviceFilterController extends Controller
{
public function filter(Feature $feature){
$marks = isset($_POST["mark"]) ? $_POST["mark"] : null;
$feature = $feature->newQuery();
if(isset($marks ))
{
foreach ($marks as $value)
{
$feature->where('device_mark', $value);
}
}
return $feature->get();
}
}
that result just one entry
You could take a different approach using whereIn(), assuming you mark input is an array of IDs like [1, 4, 8, 22].
public function filter(Request $request)
{
$features = Feature::when($request->has('mark'), function($query) use ($request) {
return $query->whereIn('device_mark', $request->mark); //Assuming you are passing an array of IDs
})->get();
return $features;
}
when() closure will only executes when you are sending 'mark' input. Doing it without when would look like this
public function filter(Request $request)
{
$features = [];
if ( $request->has('mark') && $request->mark != '' ) {
$features = Feature::whereIn('device_mark', $request->mark)->get();
} else {
$features = Feature::get();
}
return $features;
}