Laravel:Dont show error if relation dont exist - laravel

I have controller and i am getting data like this
$events= Eventm::with('teacher')->get();
Every event has one teacher then in view i am taking data like
$event['teacher']->name
its work fine if their their is relation between teacher and events. but if their is no teacher in teacher column (or Admin delete the teacher but still event contain the teacher id). the view don't render at all and show error trying to get property of non object. I want that if teacher data is deleted the view will not throw error , just show no text on
$event['teacher']->name
is it possible ?

You can do in your view
#if($event['teacher'])
<div class="whatever">$event['teacher']->name</div>
#else
<div class="whatever">Teacher not found.</div>
#endif
Another possibility is to do what you should be doing anyway: pass from controller the data to be displayed in the view. Your view should not be complicated and it should not be aware of your objects and your data, you should pass to it the data it is supposed to display. This is somethig you should be doing in a presenter or just in another class:
<?php
class ProcessEventsViewData {
private $events;
public function __construct($events)
{
$this->processData($events);
}
public function processData($data)
{
foreach($data as $event)
{
$this->processEvent($event);
}
}
public function processEvent($event)
{
$this->events[$event->id]['name'] = $event->name ?: 'Event name not found';
$this->events[$event->id]['teacher'] = $event->teacher ? $event->teacher->toArray() : array('name', 'Teacher not found');
}
public function getData()
{
return $this->events;
}
}
class MyController extends Controller {
$events = Eventm::with('teacher')->get();
$eventData = new ProcessEventsViewData($events);
return View::make('event')->with('events', $eventData->getData());
}
And in your view you now can just:
#foreach($events as $id => $event)
Event ID: {{$id}};
Event Name: {{$event['name']}};
Teacher: {{$event['teacher']['name']}};
#endforeach

Related

How do I remove the one "like" from that particular user?

Trying do create a "like system" for a simple application with Laravel and Livewire. I have managed to add likes, but I only want the user to be able to add one (1) like to a post. At the moment a user can add as many likes as he or she wants.
This is my current function to store likes:
public function storeLike()
{
// Check if the user already has liked the post
if($this->collection->likes()->exists()){
return $this->collection->likes()->delete();
}
// If not, add one like to the db
$like = $this->collection->likes()->make();
$like->user()->associate(auth()->user());
// Save the like
$like->save();
}
And the part that im struggling with is:
if($this->collection->likes()->exists()){
return $this->collection->likes()->delete();
}
It deletes all the likes for that post. So how can a disassociate, detach that like if it exists?
This is how I have made the collection:
$collection = collect();
$posts = Post::search('topic', $this->search)->with(['user'])->latest()->get();
$urls = Urls::search('topic', $this->search)->with(['user'])->latest()->get();
$news = News::search('topic', $this->search)->latest()->get();
/** Push posts to the collection */
foreach ($posts as $post) $collection->push($post);
/** Push urls to the collection */
foreach ($urls as $item) $collection->push($item);
/** Push news to the collection */
foreach ($news as $item) $collection->push($item);
I think the toggle (see docs) method could be very handy.
Let's assume we're building a component for a model called Post.
Livewire
public function clickedLike() {
$this->post->likes()->toggle(Auth::user());
}
Template
<button wire:click="clickedLike">
<3
</button>
Model
class Post extends Model {
public function likes() {
return $this->hasMany(User::class, 'likes')
}
}

Laravel: Access collection in view

I would like to display users that have sent or got message/s.
User Model:
public function messages_sender()
{
return $this->hasMany('App\Message', 'sender_id');
}
public function messages_recipient()
{
return $this->hasMany('App\Message', 'recipient_id');
}
MessageController
public function index()
{
$users = User::with('messages_recipient', 'messages_sender')->paginate(5);
//return $users;
return view('message.index',compact('users'));
}
Messages View:
{{ $user->messages_recipient['recipient_id'] }}
Result is an error in view "Undefined index: recipient_id" or when i try to access any of them (sender_id, recipient_id). I understand that not all users have messages, as i see in JSON format, so i used:
#if($user->messages_recipient->has('recipient_id'))
{{ $user->messages_recipient['recipient_id'] }}
#endif
and than error did not show.
JSON: https://pastebin.com/NFSWMp7r
As I am new to Laravel i could use some help. In similar example it worked when I needed to get users and name of their role (admin, user).
You can access the Users form the App\Message Model instead of the other way round.
Message Model:
public function senders()
{
return $this->belongsTo('App\Users', 'sender_id');
}
Message Controller
public function index()
{
$senders = Message::senders()->paginate(5);
return view('message.index',compact('senders'));
}
Dont blame me but I am not sure, if the sender_id is just right there :-P
Unfortunately, if you want unique records this will not work.
Your using the message_recipient as an array and if a key doesn't exist on an array PHP will always throw an error. The hasMany relationship returns a Collection of Message objects so you would need to use it as an object with:
#foreach($user->messages_sender as $message)
{{ $message->id }}
#endforeach
and
#foreach($user->messages_recipient as $message)
{{ $message->id }}
#endforeach
or if you just wanted all of the message ids you could do $user->messsages_recipient->pluck('id') and that would return all of the ids of the Message objects.

ManyToOne form creating linked object

Imagine these 2 entities:
Article
title
description
category <- ManyToOne
Category
name
Say we need to manage an article with a form and the category attached.
$builder
->add('name')
->add('description')
->add('category')
This one will allow me to select from existing categories.
Now I'd like to be able to create categories if needed.
Title [ ]
Description
[ ]
[ ]
Category [ ]
The category field would be a free text box.
If the text corresponds to no category, a new one would be created and attached.
I tried with some DataTransformer with no luck
I need a reusable solution to manage that because I'll need to embed it especially in another form as a collection.
How can I do it reusable ?
Suggest that you do an "if" on your category.
When you check your form submission is valid and submitted, get the 'category' data, and if not exists persist it as a new category then query for the article after.
The code might be something like this:
if ($form-isSubmitted() && $form->isValid()){
$catName = $form->get('category')->getData(); // Get category.
// Query if it exists.
$qb = $em->createQueryBuilder();
$qb->select('c')
->from('AppBundle:Category', 'c')
->where('c.name = :catName')
->setParameter('catName', $catName);
$cat_results = $qb->getQuery()->setMaxResults(1)->getOneOrNullResult();
if ($cat_results == null){
$newCat = new Category();
$newCat()->setname($catName);
$em->persist($newCat);
$em->flush();
}
else{
...
\\ Render your form etc...
}
Hopefully you get the idea. The above code is simpler, because then you create the category in the same form.
Here is what I ended up with using a DataTransformer
My ArticleType:
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description')
->add('category', CategoryType::class)
//...
A new CategoryType class:
class CategoryType extends AbstractType
{
protected $myService;
public function __construct(MyService $myService)
{
$this->myService = $myService;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new CategoryTransformer($this->myService);
$builder->addModelTransformer($transformer);
}
}
Registered as service
app.form.category_type:
class: AppBundle\Form\CategoryType
arguments: ['#app.my.service']
tags:
- { name: form.type }
And finally the transformer:
class CategoryTransformer implements DataTransformerInterface
{
// ...MyService initialization...
public function transform($category)
{
if (null === $category) {
return '';
}
return $category->getName();
}
public function reverseTransform($categoryName)
{
if (!$categoryName) {
return null;
}
$category = $this->myService->getOrCreateCategoryFromName($categoryName);
if (null === $category) {
throw new TransformationFailedException();
}
return $category;
}
}
MyService is responsible to get or create a category with the given name using the entity manager.
Quite some lines of code but once this is done, wherever I'll use my form, it can be dealt in the easy standard way:
$articleForm = $this->createForm(ArticleType::class, $article);
$articleForm->handleRequest($request);
if ($articleForm->isValid()) {
$em->persist($article);
$em->flush();
//...

how to check if a model is tagged by a specific tag

I have model Entity and related model Tag. The later serves as tags, so the relation is serviced by a pivot table
I guess it is quite easy, but I am lost.
public function tags()
{
return $this->belongsToMany('App\Models\Tag', 'entity_tags', 'entity_id', 'tag_id');
}
Now, in my view I can list all tags:
They are defined
{!!
join(', ',
array_map(function($o) {
return link_to_route('entities.profile',
$o->name,
[$o->id],
['class' => 'ui blue tag button']
);},
$object->tags->all())
) !!}
My question:
how in BLADE I can check if the Entity object has a specific capacity?
in my controller SHOW method I get one single Entity:
$object = Entity::find(34);
and then i wish to do sth if the entity is tagged by a certain tag
#if($object->capacities .... has tag= 3
// do things here
#endif
Thx
You can check if an Entity has a certain tag like this:
#if($entity->tags()->where('id', 3)->exists()) //.... has tag= 3
// do things here
#endif
You could add a public method to your Entity class wich would let you check for an existing tag on this entity :
<?php
public function hasTag($tagToMatch)
{
foreach ($this->tags as $tag)
{
if ($tag->id == $tagToMatch)
return (true);
}
return (false);
}
This would allow you to use the following code in your views :
#if ($entity->hasTag(3))
Do something
#endif

Symfony 1.4 doctrine model object data retrieve issue

In my symfony 1.4 application i'm using doctrine data models.I'm new to symfony and doctrine.I generated doctrine models from command-line after defining database table information in the schema.yml file.Those generated successfully.Then i created a custom function inside Table.class.php file.Following is that.
class Table extends BaseTable
{
public function getuname()
{
$user=new Table();
$uname=$user->getUsername();
return $uname;
}
}
I want to know how to call this inside the controller ? I called it normal MVC application's way.But i don't know whether it's correct in symfony.In symfony 1.4 manual also i couldn't find a proper way to do this.
This is my controller.
class loginActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$this->userdata = User::getuname();
}
}
Then i tried to print this inside view.
<?php
echo $userdata;
?>
But view is showing an empty page.
Update with exception details--------------------------------
stack trace
at ()
in SF_SYMFONY_LIB_DIR\plugins\sfDoctrinePlugin\lib\vendor\doctrine\Doctrine\Connection.php line 1082 ...
$message .= sprintf('. Failing Query: "%s"', $query);
}
$exc = new $name($message, (int) $e->getCode());
if ( ! isset($e->errorInfo) || ! is_array($e->errorInfo)) {
$e->errorInfo = array(null, null, null, null);
}
When using Doctrine you retrieve objects from the database using the ...Table classes (in your case it will be a TableTable class. You can use its' methods to fetch objects from DB (e.g. find($id)) and then access them. So in your case your classes should something like this:
class Table extends BaseTable
{
public function getuname()
{
return $this->getUsername();
}
}
Now it effectively becomes just an alias of getUsername().
Then in your action:
class loginActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$user = Doctrine_Core::getTable('Table')->find(123);
$this->userdata = $user->getuname();
}
}
This will print the username in your template (assuming of course that you have a user with id 123).

Resources