I am using Laravel 4 for a new project, which is a news site.
The URL for a single article should be like this:
domain.com/{category}/{shorturl}/{id}
(for example "domain.com/sports/realmadrid-barcelona/15")
In my routes.php file I have declared:
Route::get('{cat}/{shorturl}/{id}', 'ArticlesController#view');
which is working fine.
Now all I need to do is use a single Article (model) instance to pass as parameter in the Controller action to generate the URL/Route. This means, instead of passing all three parameters ('cat', 'shorturl' and 'id'), I would like to pass the Article instance.
To manage this, what I did so far is the following:
In routes.php:
Route::model('article', 'Article');
Route::get('{cat}/{shorturl}/{id}', 'ArticlesController#view');
Route::get('article/{article}', 'ArticlesController#generateUrl');
In ArticlesController.php:
public function view($cat, $urltext, $id)
{
$article = Article::findOrFail($id);
return View::make('articleView', compact(array('article')));
}
public function generateUrl(Article $article)
{
$cat = $article->category()->pluck('text');
$shorturl = $article->urltext;
$id = $article->id;
return Redirect::action('ArticlesController#view', array('cat' => $cat, 'shorturl' => $shorturl, 'id' => $id));
}
By doing this, in my view file I have something like this to produce links to other articles:
{{ $otherarticle->title }}
The problem is that, although the redirect works, the actual URL (the one shown on mouse hover) is the 'original' one (this means: "domain.com/article/123") instead of the intended ("domain.com/sports/realmadrid-barcelona/123").
Any ideas on how to accomplish this? I would like to only use $article (the Article model instance) to generate URLs, in order to keep the code as simple and clean as possible.
Thank you,
Ilias
Instead of using a redirect you need to generate the real url right away.
I would add this method to your model class
class Article extends Eloquent {
public function getUrl(){
$cat = $this->category()->pluck('text');
$shorturl = $this->urltext;
$id = $this->id;
return URL::action('ArticlesController#view', array('cat' => $cat, 'shorturl' => $shorturl, 'id' => $id));
}
}
And then just call it on the article object $article->getUrl() to generate the url
Related
I'm working on a small Symfony project and I came across an issue I don't know how to fix. I'm performing a database search via a GET request, and I'm looking for articles that are part of categories. I can select many categories and press "search", then it will return only the specific articles.
The feature is working great, but my URL isn't... "clean", I think. Working on localhost, this is what I see, for example, when I look for category "vocabulary":
localhost:8000/blog/?q=&categories[]=125
The q parameter is here to return articles when I look for a specific text (with an input field), but I think it shouldn't appear if the research only concerns categories. Right?
Also, display categories[]=125 is weird. The user should see something like categories=vocabulary&categories=grammar&categories... or something like this (of course, trying to avoid the repetition of "categories" in the URL.
How can I do this? This is what my code looks like in the repository:
/**
* Find articles related to search
*/
public function findSearch(SearchData $search): PaginationInterface
{
$query = $this
->createQueryBuilder('a')
->select('a', 'c')
->join('a.categories', 'c');
// Handling text search
if (null !== $search->q && !empty($search->q)) {
$query = $query
->andWhere('a.title LIKE :q')
->setParameter('q', "%{$search->q}%");
}
// Handling categories
if (!empty($search->categories)) {
$query = $query
->andWhere('c.id IN (:categories)')
->setParameter('categories', $search->categories);
}
$query = $query->getQuery();
return $this->paginator->paginate(
$query,
$search->page,
9
);
}
And here is what my controller looks like:
#[Route('/', name: 'blog_index')]
public function index(ArticleRepository $articleRepository, Request $request): Response
{
$data = new SearchData();
$data->page = $request->get('page', 1);
$form = $this->createForm(SearchType::class, $data);
$form->handleRequest($request);
$articles = $articleRepository->findSearch($data);
return $this->render('blog/index.html.twig', [
'form' => $form,
'articles' => $articles,
]);
}
If you need more info in order to help me, please ask.
Thanks in advance!
I want to connect articles to pages but i get error last screen.
In your home page action
public function homepage() {
$this->loadModel('Articles');
$lastArticles = $this->Articles->find('all', ['limit' => 3, 'order' => 'Articles.created DESC'])->toArray();
$this->set('lastArticles', $lastArticles);
}
View::set expects 2 parameters, one being the name of the variable in the view and the 2nd being the values of that variable for the view.
You are in the PageController.php, I never used that controller for something else than the display() method. I don't know if what you're doing is the intended use.
If you want to list your articles I'd suggest you set that up in the ArticlesController.php.
//in src/Controller/ArticlesController.php
public function home() {
$lastArticles = $this->Articles->find('all', ['limit' => 3, 'order' => 'Articles.created DESC']);
$this->set('lastArticles', $lastArticles);
}
Then you need to create a view template named corresponding to the method name in the controller (see Naming Conventions) - for the method I posted it's "home.php".
//in templates/Articles/home.php
<?php foreach ($lastArticles as $lastArticle): ?>
//.. your fields ..
<?php endforeach; ?>
I have multiple routes that look like this:
Route::get('pending-submit', 'CasesController#cases');
Route::get('submited', 'CasesController#cases');
Route::get('closed', 'CasesController#cases');
I have been looking around even in the router API documentation and I can't find a solution for my requirement other than creating multiple methods within the controller. The method does the exact same query except for adding a where clause to identify the different status between each case, what I was trying to do is have a method like this
public function cases($whereStatus = 0){
return Cases::where('status', $whereStatus)->get();
}
Instead of doing this:
public function pendingCases(){
return Cases::where('status', 0)->get();
}
public function submitedCases(){
return Cases::where('status', 1)->get();
}
public function closedCases(){
return Cases::where('status', 2)->get();
}
But I can figure a way to pass that parameter to the method from the route so I now have to create a method for each route which does not seem necessary to me. I understand I could just generate urls with the get parameter in it but I wanted to make that cleaner, is there a way for me to add that parameter without having it in the url?
By the way, I also tried something like this which did not wok:
Route::get(
'pending-submit',
array(
'uses' => 'CasesController#cases',
'params' => array(
'filter' => 0
)
)
);
EDIT:
I understand I can make URLs like https://someurl.com/cases?status=0 and can also have URLs like https://someurl.com/cases which require a different method per route however what I want is have URLs like https://someurl.com/cases and have a single method where the parameter is passed by the router instead of me getting it from the request so I can do it like this:
public function myMethod($param){
/*
* Here I access the $param without calling Request::input('someparam');
* or without Request::path() where then I have to check what path is it
*/
echo $param; /* this should already have the param from the route */
}
EDIT:
#AndyNoelker what I have is 3 different values either 0, 1 or 2
I want to have something like this
Route::get(
'cases',
array(
'uses' => 'CasesController#cases',
'status' => 0 /* this is what I need */
)
);
If not possible from the routes.php it is fine, I just want to know, all other methods you are giving me is not what I want or asking for since I already know how to do those.
You are going to have to pass the desired status in through the URL - otherwise the route will have no way of knowing which status you desire. You can either do it through URL query parameters or as a fully-fledged route parameter. I would personally suggest using a query parameter in this case, but I'll show you both.
Using Query parameters
URL
example.com/cases?status=1
Routes
Route::get('cases', CasesController#cases);
CasesController
public method cases(Request $request)
{
$input = $request->all();
$status = $input['status'];
return Cases::where('status',$status)->get();
}
Using Route parameters
URL
example.com/cases/1
Routes
Route::get('cases/{id}', CasesController#cases);
CasesController
public method cases($id)
{
return Cases::where('status',$id)->get();
}
Of course if you'd prefer that they use a slug or something other than a unique id in the route, then you'd have to adjust for that in your query, but this should give you the right idea.
I think you're looking for route parameters:
Route::get("/cases/{case}", "CasesController#cases");
This will match any of the following:
some_url/cases/pending-submit
some_url/cases/submited
some_url/cases/closed
...
Then, your function public function cases in CasesController would look like this:
public function cases($case){
if($case == "pending-submit"){
// Do Something
} else if($case == "submited") {
// Do Something Else
}
// OR
return Cases::where('status', $case)->get();
}
Etc etc. Look more into url parameters here: Documentation
Route::get('pending-submit', array('status' => 0, 'uses' => function(){
$CasesController = $app->make('CasesController');
return $CasesController->callAction('cases', $parameters = array());
}));
If I am understanding your question correctly, this should work.
Web Route
Route::get('pending-submit', [
'as' => 'pending',
'uses' => 'CasesController#cases',
'status-id' => '0'
]);
And, you can access the parameter passed with the route like below,
In Controller
$request->route()->getActions('status-id')
In View
{{ request()->route()->getAction('status-id') }}
Tested and perfectly works in L5.6
I have a page which has numerous articles. I want to give the user the ability to 'like' an article and to store that like id into a database for reuse later. Im new to Laravel and Php, so here is what i have.
I have models for Article and the Like. and i have this in the public store ArticleController.
public function store()
{
$article = new Article();
$article->body = 'new article body';
$article->title = 'new article Title';
$article->type = 'fashion';
$article->save();
$request = Request::all();
$likes = new Like();
$likes->user_id = Auth::user()->id;
$likes->article_id = $article->id;
$likes->save();
return redirect('article');
}
I followed the tutorial on laravel fundamentals but i think i missed something. This is working for me here. But now i want to change it so that it only takes the existing article and does not make a new one. When i change it to reflect this:
$article = Article::find($id);
It tells me that the $id is not defined. So how do i make $id point to the article the user wants to 'like'?
The question is So how do i make $id point to the article the user wants to 'like'?
This is quite a big/broad question but I'll try to sumarize. At first you need a route for that, for example:
Route::get('article/like/{id}', 'ArticleController#like');
Then in your ArticleController declare the like method, for example:
public function like($id)
{
// Now you can use $id
}
To clarify you, {id} in the route will take the id of the article from the URI so you may use a URI like this:
http://example.com/article/like/10 // Here 10 is the article id
So this was the idea, now implement it and modify the URI or what ever you need to make it fit in your project but remember that, if you want to pass an id to your URI then you have to use a route parameter (i.e: {id} in this case) when declaring the route and your method should recieve that parameter using an argument in the method header, i.e: public function like($id).
I am trying to print a variable fromm saveAction so i can see what is the value of that variable. I am learning Zend2 and i have continued where other developer stoped so i am trying to understand it better...This application is also using Doctrin.
I have this action which will save some data to database.
public function saveAction() {
$view = new ViewModel();
$logedUser = $this->getLogedUser();
print_r($_POST);
$shopId = (int) $this->params()->fromPost('shop_id', null);
print_r($shopId);
$shop = $this->getServiceLocator()
->get('Catalog\Model\Shop')
->getRepository()
->findOneBy(array('id' => $shopId, 'user' => $logedUser->getId()));
print_r($shop);
return $logedUser;
return $shop;
return $view;
}
I can print values from post, and variable shopId, but print_r($shop); doesn't show anything. How can i see the value of shop variable?
Try this
echo $shop->__toString();
Hi there you might want to try this one:
print_r($this->getAllParams());
instead of using $_POST
$shop = $this->getServiceLocator()
->get('Catalog\Model\Shop')
->findOneBy(array('id' => $shopId, 'user' => $logedUser->getId()));
please remove ->getRepository() from your code, then you will get your result.
At this point we dont know what the Service/Factory 'Catalog\Model\Shop' does. I assume it get's the Entity manager. The query looks ok to me 2. But having 3 return's is just wrong!
Your view will never have the $shop; nor the $view; variable in your .phtml view File. In ZF2 you can just return a Array to your view like so:
return array('shop' => $shop, 'logedUser' => $logedUser);
This will save those variables within your save.phtml
in /yourmodule/view/yourcontroller/save.phtml
If you want to set the .phtml matching yourself you indeed could use the view model like you tried in your code the procedure is a litle diffrent then. It could look like this:
$viewModel = new ViewModel(array(
'logedUser' => $logedUser,
'shop' => $shop,
));
$viewModel->setTemplate('yourmodul/yourcontroller/save');
return $this->getContainerViewModel($viewModel);
Once you have that you can just access your variables in the save.phtml template file like so:
<?php echo $shop->getSomething(); ?>
You did not show us the Shop entity but I assume it has methods like getName(), __toString() etc. You can just call these Object methods within your view.
If you still have trouble understanding the mvc concept of zf2 you might want to re-read the zf2 documentation.
You have to show us what Catalog\Model\Shop and what query are you using for getting your data. Is there possibility that your query just getting null because it fails to get anything from database ? Do you have any kind of checks in your model to find out is your result from query good?