Trying to get property of non-object when url has hyphen in it

I have added 2 records to my database. One has 'slug' of pool, and the other of swimming-pool. These records are displayed in navigation and when they are clicked on, I want to use the database slug record instead of the ID in the url.

So, instead of mysite.com/facilities/21/

I want mysite.com/facilities/swimming-pool

But this only sort of works. As soon as I have a hyphen, it breaks.

If I go to mysite.com/facilities/pool then then everything works fine.

But if I go to mysite.com/facilities/swimming-pool I get the error: Trying to get property of non-object

I suspect that this is due to the setup in my core which has this code:

class Core {
	
	protected $currentController = 'Pages';
	protected $currentMethod = 'index';
	protected $params = [];
	
	public function __construct() {
		$url = $this->getUrl();
		
		// Look in Controllers for first value
		if(file_exists('../app/controllers/' . ucwords($url[0]) . '.php')) {
			//if exists, set as controller
			$this->currentController = ucwords($url[0]);
			// Unset zero index
			unset($url[0]);
		}
		
		// Require the controller
		require_once '../app/controllers/' . $this->currentController . '.php';
		
		// Instantiate controller
		$this->currentController = new $this->currentController;
		
		
		// Check for second part of url
		if(isset($url[1])) {
			
		        //potential issue is here
                        $url[1] = str_replace('-', '_', $url[1]);
			
			// check to see if method exists in controller
			if(method_exists($this->currentController, $url[1])) {
				$this->currentMethod = $url[1];
				// Unset 1 index
				unset($url[1]);
			}	
		}
		
		// Get params
		$this->params = $url ? array_values($url) : [];
		
		// Call a callback with array of params
		call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
	}
	
	public function getUrl() {
		if(isset($_GET['url'])) {
			$url = rtrim($_GET['url'], '/');
			$url = filter_var($url, FILTER_SANITIZE_URL);
			$url = explode('/', $url);
			return $url;
		}
	
	}
}

Open in new window


If I remove this line :

    $url[1] = str_replace('-', '_', $url[1]);

Open in new window


It then works. But then removing that breaks my other pages where for example I have hard-coded page names like contact-us where my controller is called contact_us. So, I need that line in order to achieve that.
LVL 1
Black SulfurAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

David Johnson, CD, MVPOwnerCommented:
have you tried enclosing the url in quotes?
0
Black SulfurAuthor Commented:
@David,

Sorry, I don't really understand what you mean?
0
Julian HansenCommented:
Where do you get the error - what line?
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

Black SulfurAuthor Commented:
Hi Julian,

The error is from this:

      
public function index($slug)
	{
		
		$facilities = $this->facilityModel->getFacilityById($slug);
		
		$data  = [
			
			'name' => $facilities->name,
			'description' => $facilities->description
		];
		
		$this->view('facilities/index', $data);
	}

Open in new window


And these are the 2 lines it is pointing to:

'name' => $facilities->name,
'description' => $facilities->description

Open in new window

0
Black SulfurAuthor Commented:
If I remove this line:

  $url[1] = str_replace('-', '_', $url[1]);

Open in new window


from the Core class, it works fine, which is why I think this line may have something to do with it.
0
Black SulfurAuthor Commented:
So, I have found a clue.

My URL format in the Core class is:

URL format - /controller/method/params

and that means my current url is /facilities/params e.g.: facilities/swimming-pool , meaning that I am missing my method name. But my method name is index

So, If I change my url to facilities/index/swimming-pool then it works, but that is ridiculous. I don't want the index name in there.
0
Julian HansenCommented:
Then you need to change Core.php to look for a default method when no method is specified in the URL.
0
Steve BinkCommented:
To clarify just a little, you need to identify when url[1] is not a valid method, and fallback to an arbitrary, default method, like index.  For example:
		if(isset($url[1])) {
			
		        //potential issue is here
                        $url[1] = str_replace('-', '_', $url[1]);
			
			// check to see if method exists in controller
			if(method_exists($this->currentController, $url[1])) {
				$this->currentMethod = $url[1];
				// Unset 1 index
				unset($url[1]);
			}	
                   /* Here's the new code */
                   else {
                       $this->currentMethod = 'index';
                   }
		}

Open in new window

That said, the error you are receiving is "Trying to get property of non-object".  If you are receiving the error on the line you indicated, that means $facilities was not able to instantiate.  You may also need to troubleshoot why that is the case.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Black SulfurAuthor Commented:
Still struggling with this. @ Steve, I tried your code but it makes no difference. And I can't find the issue regarding the non-object error.

If I remove this line on the core:

$url[1] = str_replace('-', '_', $url[1]);

Open in new window


Then the error goes away and the database info displays as it should. As soon as I add that one line back, it breaks which is why I think perhaps the problem is in the Core.php, not in that particular method.
0
Slick812Commented:
I hope this will help, BUT I can not see enough in the code you present, to know the many factors that may be used to obtain a portion of the URL and parse (analyze) the sub-url string. Many programming URL converters need a consistent way to set a URL section, it appears that this one uses a line-space "a_name" and NOT a hyphen "a-name" for this purpose. So you might try changing your name with "_" from,
    swimming-pool
to
    swimming_pool
for consistency
but I can not know why you want to use a hyphen?
0
Steve BinkCommented:
Yeah, there's something backwards here.  I think you'll have to trace through your controller instantiation to find out what exactly is going on.  I would start by putting some traces on $url.  Find out exactly what each value is as you are going through it.  Also, get a debug_backtrace() just before the line generating the error.  Perhaps the context of the error is different than you are assuming.
0
Steve BinkCommented:
I also meant to mention the same concept as Slick812 - a hyphen is a poor choice for any system based on naming convention.  As your names propagate between the file system, variable names, and class names, you'll find you have to constantly manage the hyphen-underscore situation.  It is certainly more trouble that it is worth, and mishandling it can result in problems very similar to what you are experiencing now.
0
Black SulfurAuthor Commented:
Just a quick note regarding the hyphen. Isn't that standard in URL's and required for good SEO? I haven't seen any url's with underscores in them to be honest.

I think it is more common to see: example.com/contact-us and not example.com/contact_us

But I could of course be misunderstanding what you are saying...
0
Steve BinkCommented:
I don't disagree in terms of SEO.  I was speaking strictly from the context of the framework.  As you've already seen, you need to standardize the names as they come into the system.

You do make an attempt at this with str_replace(), though you should have a dedicated function to modify the names as required, instead of an ad-hoc function call.  (Imagine if your manipulation required more than the one replacement...)  Even so, you're already running into some difficulty when your term actually contains a hyphen vs using the hyphen as a space replacement in the URL.  IMO, the ideal would be to have a registry to assist with routing to the proper MVC components.  E.g., Drupal uses content type, and Joomla uses the option query string variable.
0
Black SulfurAuthor Commented:
I think until I get a better grasp of OOP and MVC, it might be easier for me to simply change my url to the format that was initially set, i.e.:

/controller/method/params which is equal to /facilities/index/swimming-pool.

But, obviously give my method a move meaningful name as opposed to index. But that in itself is tricky. What could I possibly replace index with that would make sense?

For posts I have /posts/article/article-name which is okay-ish.

establishment/facilities/swimming-pool also seems ridiculous, haha.
0
Slick812Commented:
??????
Not sure I am understanding what is necessary for for this, for it to work or some concept of SEO ? ?
Just My opinion, but If it was me I would not use a - or _ and just have it as

         establishment/facilities/swimmingpool

, and that works (according to what you say),

Sometimes these URL do not need to be human readable, as it's the Server (a computer) that uses the string names for different operations as to directory names, , ,  so I might shorten it to just "swimpool" or maybe even "sp"
0
Black SulfurAuthor Commented:
@Slick, regarding hyphens and SEO, please check the link below, straight from MOZ.

When necessary for readability, use hyphens to separate words. URLs should not use underscores, spaces, or any other characters to separate words.

https://moz.com/learn/seo/url

Also, my URL is generated by the title inputted by the user. If the user wants to add a facility via the CMS I created for them, I have a function which breaks up the title they input into a friendly url. I have no control what they input. So if they input "swimming pool", the function changes it to swimming-pool and that is my friendly url string.
0
Slick812Commented:
OK I looked at and read some of the link you gave as "SEO best practice",
But I did not say what I said before as "some concept of SEO" to "argue against" any or advocate any SEO considerations, What I was trying to say, is that you need to get this "Working" before you try and optimize for search engines. So far I have not seen any thing that gets you to have this working, AND use the hyphen -  , , as you say this code for conversion -
             $url[1] = str_replace('-', '_', $url[1]);
prevents the use of the hyphen in your friendly url of "swimming-pool"
I would think that the URL parser (string analyzer) already has a "Special" use for the hyphen and therefore had to add the converter -
             $url[1] = str_replace('-', '_', $url[1]);
to make sure that the URL hyphens don't screw up the parse operations of the URL analyzer,

Maybe, In order to use your friendly url of "swimming-pool", you will need to rewrite the current URL analyzer engine code to accommodate any characters that you deem necessary for your site to be a SEO winner.
0
Black SulfurAuthor Commented:
Hi Slick,

If you see some of my previous comments, I can get it to work but it has to be in the format /contoller/method/params eg: posts/article/a-blog-post, in order to work.

So, if I change the url to facilities/index/swimming-pool, it works but as soon as I leave out the method name (index), it doesn't work.
0
Slick812Commented:
?  ? ?
as I said, there need to be adjustments, but I can not see a way to adjust it?

It seems to me to be in the
    $url[1] = str_replace('-', '_', $url[1]);
// The CURENTCONTROLER METHODS aparently uses _ and not hyphens
     if(method_exists($this->currentController, $url[1])) {
     $this->currentMethod = $url[1];
     unset($url[1]);
     }

Open in new window

In the conversion from hyphens, the line -
     (method_exists($this->currentController, $url[1]))
seems to NOT FIND the method needed if the "index" (a method in the controler) is not used,

as far as this code would indicate to me, when this line is used LATER -
    call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
there may not be any  $this->currentMethod when the   $this->params  contains any of the hyphen url strings, But I have no Idea how to adjust that? ?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.