This is my first question in this forum so please be patient to me ;)
I'm making a blog using Laravel and
I have a page with a view of all articles inside my database
enter image description here
Last column is "Action" column whet after hit the button you can see single article.
The problem is to show each content (title,subtitle etc.) i must create loooong UrL like this
http://127.0.0.1:8000/article/Test/Test/test/2020-05-08%2016:00:00
Is there any chance to cut URL to be like that:
http://127.0.0.1:800/article/Test
and still have all content?
Files
web.php
Route::get('article/{title_article}/{subtitle_created}/{text_article}/{created_at}','ReadController#index');
Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Article;
class ReadController extends Controller
{
public function index($title_article,$subtitle_article,$text_article,$created_at)
{
return view('article',compact('title_article','subtitle_article','text_article','created_at'))->with('title','Artykuł');
}
}
You should use the primary key (probably an incrementing id) of your database object (App\Article) to identify the object. Laravel has a wonderful function to automatically convert the primary key (id) in the route to an eloquent model.
In your case:
Route::get('article/{article}','ReadController#index');
and
public function index(Article $article) { ... }
I hope this helps you. If you don't understand parts of it, feel free to ask :)
Related
I have a project I'm working on right now, in which I created a database to hold some info. I've already created a view and a controller where I can add data to the DB and it works. But for some reason when I try to use on a view to list my information it won't work.
Here's my model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Banner extends Model
{
protected $fillable = ['descricption','image'];
}
And these are the first few lines of my view which laravel point to error:
#php
use\app\Banner;
$banner = new Banner;
$banners = Banner::all();
#endphp
Whenever I try to open this view, I get the "Class 'app\Banner' not found" error. What am I doing wrong? Since it worked to add data to the database before, and I did remember of putting the use\app\Banner;
The namespace is App not app. Always act like case sensitivity matters and you won't have these problems.
use App\Banner;
Side Note: you can pass this data to your view instead of having to do this query in your view.
I'm learning Laravel and I've created a basic blog. Now, I'm trying to create something similar to an autoblog where posts change status based on either start_date or end_date. So I've created an enum table in my migration with the statuses I need to use. Right now, what I'm trying to do is change the post status to Upcoming if the date and time are greater than today but I'm not having any luck. Initially, I created an event and put the code below in the listener but is working (or not working) in the same way as in the observer. I read that it would be better in the observer if there will be several events.
The flow would be, when the post is created, check the start_date and change the status if the date is greater than today. The code below changes the status to Upcoming if I change it to creating, instead of created but it still doesn't take the start_date into account because it adds it to every post, regardless of the start_date. I tried using an if statement but I kept getting stuck. What am I missing or doing wrong?
Eventually, my goal is for the posts to change the status automatically without any user-initiated action. Perhaps, I could use Laravel queues for that but I haven't got that far yet. For the moment, I'm trying to get past this one.
<?php
namespace App\Observers;
use App\Models\Post;
use Carbon\Carbon;
class PostObserver
{
public function created(Post $post)
{
$post = Post::whereDate('start_date', '>', Carbon::now()->toDateString(){
$post->post_status = 1 // 1 = Upcoming status
});
}
}
Got it working like this, kind of a combination of the two responses, for which I'm thankful:
if (Carbon::parse($post->start_date)->greaterThan(Carbon::now()))
{
$post->post_status = 1;
}
Use method creating
<?php
namespace App\Observers;
use App\Models\Post;
use Carbon\Carbon;
class PostObserver
{
public function creating(Post $post)
{
if ($post->start_date->greaterThan(Carbon::now())) {
$post->post_status = 1;
}
}
}
Creating method will be invoked before post is saved to database. In that point you make check and only in case that start_date is bigger than current timestamp post_status will get value of 1. If you need you can set else block where you give value of 0 to post status in case it is not db default or if there is need for something like that.
I am new in Laravel pardon me if question is silly. I have seen a doc where they used
For get request
Route::get("tags/{id}","TagsController#show");
For put request
Route::put("tags/{tag}","TagsController#update");
What is the difference and benefit between this ? I understood 1st one, confusion on put route.
There’s no real difference as it’s just a parameter name, but you’d need some way to differential parameters if you had more than one in a route, i.e. a nested resource controller:
Route::get('articles/{article}/comments/{comment}', 'ArticleCommentController#show');
Obviously you couldn’t use just {id} for both the article and comment parameters. For this reason, it’s best to use the “slug” version of a model for a parameter name, even if there’s just one in your route:
Route::get('articles/{article}', 'ArticleController#show');
You can also use route model binding. If you add a type-hint to your controller action for the parameter name, Laravel will attempt to look up an instance of the given class with the primary key in the URL.
Given the route in the second code example, if you had a controller that looked like this…
class ArticleController extends Controller
{
public function show(Article $article)
{
//
}
}
…and you requested /articles/123, then Laravel would attempt to look for an Article instance with the primary key of 123.
Route model binding is great as it removes a lot of find / findOrFail method calls in your controller. In most instances, you can reduce your controller actions to be one-liners:
class ArticleController extends Controller
{
public function show(Article $article)
{
return view('article.show', compact('article'));
}
}
Generally there's no practical difference unless you define a custom binding for a route parameter. Typically these bindings are defined in RouteServiceProvider as shown in the example in the docs
public function boot()
{
parent::boot();
Route::model('tag', App\Tag::class);
}
When you bind tag this way then your controller action can use the variable via model resultion:
public function update(Tag $tag) {
// $tag is resolved based on the identifier passed in the url
}
Usually models are automatically bound so doing it manually doesn't really need to be done however you can customise resolution logic if you do it manually
Normal way
Route::get("tags/{id}","TagsController#show");
function($id)
{
$tag = Tag::find($id);
dd($tag); // tag
}
With route model bindings
Route::put("tags/{tag}","TagsController#update");
function(Tag $tag) // Tag model binding
{
dd($tag); // tags
}
ref link https://laravel.com/docs/5.8/routing#implicit-binding
It's just a convention. You can call it all you want. Usually, and {id} refers to the id in your table. A tag, or similarly, a slug, is a string value. A tag could be 'entertainment' for video categories, while 'my-trip-to-spain' is a slug for the description of a video.
You have to chose the words what you are comfortable with. The value will be used to find in your database what record is needed to show the correct request in the view. Likewise you can use video/view/{id}/{slug} or any combination thereof.
Just make sure your URLs don't get too long. Because search engines won't show your website nicely in search results if you do. Find the balance between the unambiguous (for your database) and logic (for your visitors).
Check this out: Route model bindings
Use id, Laravel will get the id from route, and it will be the tag's id, it is integer.
function show($id) {
$tag = Tag::find($id);
}
Use tag, Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name.
In URL, your tag parameter is integer, however in your controller action $tag will be a model object:
function action(Tag $tag) {
$tag->name;
}
So you don't need to get the $tag by eloquent in your controller action. You just need to specify it is From model Tag $tag
It will do it automatically.
I want my urls to look like:
www.domain.com/catalog/category_name/category_id/product_name/product_id.
How should my controllers look like to accomplish this?
It's ok for the Controller to have Catalog and Function category_name in it.
But what will be my product controller and function. How can I make a structure like this.
Do I need to have a specific file structure?
I use CodeIgniter framework. Thanks for your help.
In general the controller must not be changed (if it accepts the product id as parameter).
All other information can then be put in the url from the database (querying via the product id and getting related information) through URI Routing changes.
your controller method should be like this
<?
//..
public function category_name($category_id,$product_name,$product_id){
// some cool code
}
//..
?>
As you question is very vague - so is my answer - but this function achieves what you asked
Class Catalog extends CI_Controller
{
public function category_name ($category_id, $product_name, $product_id)
{
// your function
}
}
I have a table of data from a database that I want to display on various pages of my website. Ideally, i would like to just have an include or something that will go off and get the data, and return the html table. The html and data will be identical everytime I need to use this.
I wanted to know the best way of doing this
Thanks
EDIT
If this helps, something similar to a Django "inclusion" custom tag...for any django developers reading
you need to pass the variable $data to the view method.
This is your code:
function load_my_view(){
$this->load->model('my_table');
$data['my_results'] = $this->my_table->my_data();
$this->load->view('my_view');
}
Please change it to this in order to load the $data into the view:
function load_my_view(){
$this->load->model('my_table');
$data['my_results'] = $this->my_table->my_data();
$this->load->view('my_view',$data);
}
You should use a function in a model to fetch the data you need. Your controller calls the model function and sends the returned information to a view. You don't need to use traditional php includes with Codeigniter. I recommend a review of the user guide. It's very good and will tell you all the basic stuff you need to know to develop with CI. But to get you started, you watn to use Models, Views, and Controllers. Your url will tell CI what controller and function inside that controller to run. If your url is
http://www.example.com/my_controller/load_my_view
Then CI will do what is inside the load_my_view function in the my_controller controller. function load_my_view in turn instantiates a model "my_table" and runs a database query, returns information that the controller sends to the view. A basic example follows:
Your model
class my_table extends CI_Model{
function my_data(){
$this->db->select('column_1,column_2,column_3');
$this->db->from('my_table');
$query = $this->db->get();
if($query->num_rows()>0){
$result = $query->result();
}
else{
$result = false;
}
return $result;
}
}
Your controller
class my_controller extends CI_Controller{
function load_my_view(){
$this->load->model('my_table');
$data['my_results'] = $this->my_table->my_data();
$this->load->view('my_view');
}
}
Your View
<ul id = "my_db_results">
<?php foreach($my_results as $result):?>
<li><?php echo $result->column_1." : ".$result->column_2." ( ".$result->column_3." )";?></li>
<?php endforeach;?>
</ul>
It looks like a good oportunity to use cache: http://codeigniter.com/user_guide/libraries/caching.html
Ok, so here is one thing that worked for me, but its definitely not perfect.
I created a view in which made a call to the model getting the data then put the data into a table. This way, I only have to include this view to put the table anywhere.
I understand this completely ruins the point of having a MVC framework, but hopefully it demonstrates what I want to do...and it works